luogu P1083 借教室
小水题吧
二分能处理到的询问即可
用差分维护前x个订单之后的值
最后求一遍前缀和 如果爆负就是有不满足的
复杂度O((m+n)lgm)
或者区间加和区间最小值线段树也行(常数略大)
Code:(线段树)
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include <iostream> 5 #include<algorithm> 6 #define rep(i,a,n) for(int i = a;i <= n;++i) 7 #define per(i,n,a) for(int i = n;i >= a;--i) 8 #define inf 2147483647 9 #define ms(a,b) memset(a,b,sizeof a) 10 using namespace std; 11 typedef long long ll; 12 ll read() { 13 ll as = 0,fu = 1; 14 char c = getchar(); 15 while(c < '0' || c > '9') { 16 if(c == '-') fu = -1; 17 c = getchar(); 18 } 19 while(c >= '0' && c <= '9') { 20 as = as * 10 + c - '0'; 21 c = getchar(); 22 } 23 return as * fu; 24 } 25 //head 26 const int N = 1000006; 27 int n,m; 28 int a[N]; 29 30 #define ls t<<1 31 #define rs t<<1|1 32 int p[N<<2],add[N<<2]; 33 void pdown(int l,int r,int t) { 34 if(!add[t]) return; 35 p[ls] += add[t],p[rs] += add[t]; 36 add[ls] += add[t],add[rs] += add[t]; 37 add[t] = 0; 38 } 39 void build(int l,int r,int t) { 40 if(l == r) return void(p[t] = read()); 41 int m = l+r >> 1; 42 build(l,m,ls),build(m+1,r,rs); 43 p[t] = min(p[ls],p[rs]); 44 } 45 void update(int L,int R,int c,int l,int r,int t) { 46 if(L <= l && r <= R) { 47 p[t] -= c; 48 add[t] -= c; 49 return; 50 } 51 pdown(l,r,t); 52 int m = l+r >> 1; 53 if(L <= m) update(L,R,c,l,m,ls); 54 if(R > m) update(L,R,c,m+1,r,rs); 55 p[t] = min(p[ls],p[rs]); 56 } 57 int query(int L,int R,int l,int r,int t) { 58 if(L <= l && r <= R) return p[t]; 59 pdown(l,r,t); 60 int m = l+r >> 1; 61 int ans = inf; 62 if(L <= m) ans = min(ans,query(L,R,l,m,ls)); 63 if(R > m) ans = min(ans,query(L,R,m+1,r,rs)); 64 return ans; 65 } 66 67 int main() { 68 n = read(),m = read(); 69 build(1,n,1); 70 rep(i,1,m) { 71 int d = read(),x = read(),y = read(); 72 update(x,y,d,1,n,1); 73 if(query(x,y,1,n,1) < 0) { 74 printf("-1\n%d\n",i); 75 return 0; 76 } 77 } 78 puts("0"); 79 return 0; 80 }
> 别忘了 总有人在等着你