【NOIP2012-Day2-T2-换教室】
好吧D2T2考线段树还行。
其实是不考的。
题目大意就是给一个区间$[l,r]$,然后让这个区间减掉$d$,这样算一次操作
然后给你$m$次操♂作,求第几次操作之后开始出现负数。
显然线段树乱搞是可以AC的。
但是我们深知2012年的出题人还没有那么毒瘤。
于是我们发现,这个问题是满足单调性的。
也就是说,第$i$次操作如果有负数,那么$i+1$次也有
同理$i$没有那么$i-1$也没有
所以是一道二分,然后每次判断的时候用差分维护一下,就顺利AC了
代码(吼吼,check♂it♂out)
1 #include<bits/stdc++.h> 2 #define maxn (1000000+500) 3 using namespace std; 4 int n,m; 5 int r[maxn],d[maxn]; 6 int s[maxn],t[maxn]; 7 int del[maxn]; 8 9 int check(int N) 10 { 11 memset(del,0,sizeof(del)); 12 for (int i=1;i<=N;++i) 13 { 14 del[s[i]]+=d[i]; 15 del[t[i]+1]-=d[i]; 16 } 17 int now=0; 18 for (int i=1;i<=n;++i) 19 { 20 now+=del[i]; 21 if (now>r[i]) return 0; 22 } 23 return 1; 24 } 25 26 int main() 27 { 28 scanf("%d%d",&n,&m); 29 for (int i=1;i<=n;++i) scanf("%d",&r[i]); 30 for (int i=1;i<=m;++i) 31 scanf("%d%d%d",&d[i],&s[i],&t[i]); 32 33 int ans=0,l=0,r=n; 34 while (l<=r) 35 { 36 int mid=(l+r)>>1; 37 if (check(mid)) 38 { 39 ans=mid; 40 l=mid+1; 41 } 42 else r=mid-1; 43 } 44 45 if (ans==n) puts("0"); 46 else printf("-1\n%d\n",ans+1); 47 48 return 0; 49 }
好吧要是写线段树可能思维难度更低