题目:
n天,第i天有a[i]个教室可以借出。m个订单,第i个订单需要[li,ri]区间内借xi个教室。问到第几个订单无法满足。
对于100%的数据,有1≤n, m≤106, 0≤ri, dj≤109, 1≤sj≤tj≤ n。
做法:
每个订单我们都分2步走:
1、确定能不能满足;2、完成订单,把教室借出去。
第一步我们需要知道当前[li,ri]区间是不是所有数≥xi。我们只需知道[li,ri]区间的最小值即可。
第二步把教室借出去,则[li,ri]区间可借出的教室数量都减xi。区间更新操作。
所以很明显我们可以用线段树维护区间更新和区间最小值查询来解决这个问题。
代码:
#include <bits/stdc++.h>
#define lson (rt<<1)
#define rson (rt<<1|1)
#define debug(a) cout << #a ": " << a << endl
#define IOS ios::sync_with_stdio(false), cin.tie(0)
using namespace std;
typedef long long ll;
inline int read(void){
char ch = getchar();
int ans = 0;
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) ans = ans*10 + ch-'0', ch = getchar();
return ans;
}
const int N = 1e6 + 7;
struct node{
int mn, lazy;
}T[N<<2];
int n, m, a[N];
void pushup(int rt){
T[rt].mn = min(T[lson].mn, T[rson].mn);
}
void build(int l, int r, int rt){
if (l == r){
T[rt].mn = a[l]; return;
}
int mid = (l+r) >> 1;
build(l, mid, lson);
build(mid+1, r, rson);
pushup(rt);
}
void pushdown(int rt){
int x = T[rt].lazy; T[rt].lazy = 0;
T[lson].mn -= x, T[lson].lazy += x;
T[rson].mn -= x, T[rson].lazy += x;
}
void update(int x, int L, int R, int l, int r, int rt){
if (L <= l && r <= R){
T[rt].mn -= x;
T[rt].lazy += x;
return;
}
if (T[rt].lazy) pushdown(rt);
int mid = (l+r) >> 1;
if (L <= mid) update(x, L, R, l, mid, lson);
if (R > mid) update(x, L, R, mid+1, r, rson);
pushup(rt);
}
int query(int L, int R, int l, int r, int rt){
if (L <= l && r <= R){
return T[rt].mn;
}
if (T[rt].lazy) pushdown(rt);
int mid = (l+r) >> 1;
if (L > mid){
return query(L, R, mid+1, r, rson);
}else if (R <= mid){
return query(L, R, l, mid, lson);
}else{
return min(query(L ,R, l, mid, lson), query(L, R, mid+1, r, rson));
}
}
int main(void){
n = read(), m = read();
for (int i = 1; i <= n; ++i){
a[i] = read();
}
build(1, n, 1);
for (int i = 1; i <= m; ++i){
int x = read(), l = read(), r = read();
if (query(l, r, 1, n, 1) >= x){
update(x, l, r, 1, n, 1);
}else{
printf("-1\n%d\n", i); return 0;
}
}
printf("0\n");
return 0;
}
京公网安备 11010502036488号