[CodeVS 1217]借教室
转载请注明出处:http://danihao123.is-programmer.com/
很容易想到线段树水过。
很可惜,这样估计也就70分。
然后这个问题是符合单调性的……可以二分答案哒。不过怎么判定?
不知道诸位还记得差分序列?记得就好,用差分序列的方法维护即可。
等等,我怎么感觉你这个做法是[tex]O(nlogn)[/tex]的,能过?
推荐一个行之有效的优化:注意一下每一次修改都是在之前的基础上反悔或前进几次,所以就可以直接在原基础上修改差分序列辣~这样效率是很高滴~
代码:
#include <cstdio> const int maxn=1e6+5; typedef long long ll; ll A[maxn]; int l[maxn],r[maxn]; ll d[maxn]; ll C[maxn]; int n,m,last=0; bool Check(int x){ register int i,cnt=0; if(x>last) for(i=last+1;i<=x;i++){ C[l[i]]+=d[i]; C[r[i]+1]-=d[i]; } if(x<last) for(i=x+1;i<=last;i++){ C[l[i]]-=d[i]; C[r[i]+1]+=d[i]; } last=x; for(i=1;i<=n;i++){ cnt+=C[i]; if(cnt>A[i]) return false; } return true; } int main(){ register int i,L,M,R; scanf("%d%d",&n,&m); for(i=1;i<=n;i++){ scanf("%lld",&A[i]); } for(i=1;i<=m;i++){ scanf("%lld%d%d",&d[i],&l[i],&r[i]); } L=1; R=m+1; while(L<R){ M=L+(R-L)/2; if(Check(M)){ L=M+1; }else{ R=M; } } if(L==m+1) puts("0"); else printf("-1\n%d\n",L); return 0; }