线段树可以搞,思维难度确实小一些,但是复杂度可怕 O(mnlogn)
正解:差分+二分,复杂度(nlogm)且代码短。
总之,能用差分、前缀和、二分搞得尽量不要上线段树,代码长,常数还大,迫不得已再用。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #define mid (l+r>>1) 4 using namespace std; 5 typedef long long ll; 6 7 const int Maxn = 1e6+10; 8 9 ll read(){ 10 ll a = 0;char l = ' ',c = getchar(); 11 while(c < '0'||c > '9')l = c,c = getchar(); 12 while('0' <= c&&c <= '9')a = a*10+c-'0',c = getchar(); 13 if(l == '-')return -a;return a; 14 } 15 16 ll ql[Maxn],qr[Maxn],qc[Maxn],num[Maxn],cf[Maxn]; 17 ll ans,l,r,n,m; 18 19 bool check(int x){ 20 for(int i = 1;i <= n;i++)cf[i] = num[i]-num[i-1]; 21 for(int i = 1;i <= x;i++)cf[ql[i]] -= qc[i],cf[qr[i]+1] += qc[i]; 22 ll now = 0;bool flag = true; 23 for(int i = 1;i <= n;i++){ 24 now += cf[i]; 25 if(now < 0){flag = false;break;} 26 } 27 return flag; 28 } 29 30 int main(){ 31 n = read(),m = read(); 32 for(int i = 1;i <= n;i++)num[i] = read(); 33 for(int i = 1;i <= m;i++)qc[i] = read(),ql[i] = read(),qr[i] = read(); 34 l = 1,r = m; 35 while(l <= r) 36 if(check(mid))l = mid+1; 37 else ans = mid,r = mid-1; 38 if(ans)printf("-1 %d",ans);else putchar('0'); 39 return 0; 40 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 4 using namespace std; 5 6 struct node{ 7 int l,r,w,laz,minx; 8 }tree[4000010]; 9 10 int read(){ 11 int ans = 0;char last = ' ',ch = getchar(); 12 while(ch < '0'||ch > '9')last = ch,ch = getchar(); 13 while('0' <= ch&&ch <= '9')ans = ans*10+ch-'0',ch = getchar(); 14 if(last == '-')return -ans;return ans; 15 } 16 17 void build(int d,int l,int r){ 18 tree[d].l = l,tree[d].r = r; 19 if(l == r){ 20 tree[d].minx = read(); 21 return; 22 } 23 int mid = (l+r)/2; 24 build(d<<1,l,mid),build(d<<1|1,mid+1,r); 25 tree[d].minx = min(tree[d<<1].minx,tree[d<<1|1].minx); 26 } 27 28 void down(int d){ 29 tree[d<<1].minx += tree[d].laz; 30 tree[d<<1|1].minx += tree[d].laz; 31 tree[d<<1].laz += tree[d].laz; 32 tree[d<<1|1].laz += tree[d].laz; 33 tree[d].laz = 0; 34 } 35 36 void change(int d,int l,int r,int x){//cout << d << ' ' << l << ' ' << r << endl; 37 //printf("%d %d ",tree[d].l,tree[d].r); 38 if(l <= tree[d].l&&tree[d].r <= r){ 39 tree[d].laz += x; 40 tree[d].minx += x; 41 return; 42 } 43 down(d); 44 int mid = (tree[d].l+tree[d].r)>>1; 45 if(l <= mid)change(d<<1,l,r,x); 46 if(mid < r)change(d<<1|1,l,r,x); 47 tree[d].minx = min(tree[d<<1].minx,tree[d<<1|1].minx); 48 } 49 50 int ask(int d,int l,int r){ 51 int i = d; 52 // printf("%d %d %d %d ",i,tree[i].l,tree[i].r,tree[i].minx); 53 if(l <= tree[d].l&&tree[d].r <= r)return tree[d].minx; 54 down(d); 55 int mid = (tree[d].l+tree[d].r)>>1,val = 0x7f; 56 if(l <= mid)val = min(val,ask(d<<1,l,r)); 57 if(mid < r)val = min(val,ask(d<<1|1,l,r)); 58 return val; 59 } 60 61 int main(){ 62 int n,m,x,y,z,val; 63 n = read(),m = read(); 64 build(1,1,n); 65 for(int i = 1;i <= m;i++){ 66 z = read(),x = read(),y = read(); 67 change(1,x,y,-z); 68 val = ask(1,x,y); 69 if(val < 0){ 70 printf("-1 %d",i); 71 return 0; 72 } 73 } 74 printf("0 "); 75 return 0; 76 }