差分思想:考虑[l,r]借d个教室,那么让s[l]+=d,s[r+1]-=d,然后对s求一遍前缀和,就是每天的情况,就可以判断是否超出。
然后可以二分。
线段树最多95 23333333......
其实是抄的黄学长的代码。。。不想写了。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,m,ans,a[1000010],d[1000010],x[1000010],y[1000010],s[1000010],sum; template <class T> T get(T &u){ char x;for(;!isdigit(x=getchar());); for(u=x-48;isdigit(x=getchar());u*=10,u+=(x-48)); ungetc(x,stdin);return u; } bool judge(int v) { memset(s,0,sizeof(s));sum=0; for(int i=1;i<=v;i++) {s[x[i]]+=d[i];s[y[i]+1]-=d[i];} for(int i=1;i<=n;i++) { sum+=s[i]; if(sum>a[i])return 0; } return 1; } int main() { get(n),get(m); for(int i=1;i<=n;i++)get(a[i]); for(int i=1;i<=m;i++) get(d[i]),get(x[i]),get(y[i]); int l=1,r=m; while(l<=r) { int mid=(l+r)>>1; if(!judge(mid)){ans=mid;r=mid-1;} else l=mid+1; } if(!ans)printf("0"); else printf("-1 %d ",ans); return 0; }