我们二分一下答案,看哪个是最后一个可以被满足的条件。
每次二分得到mid之后,我们就把1~mid的条件用差分实现区间加,再把这个差分数组前缀和一下得到每个位置需要的教室数,判断一下就可以了。
这里我加了一个小优化,每次修改差分数组都从上一次修改到的点开始修改(即吧差分数组的信息由 1~mid' 改为 1~mid),这样可以证明总的修改差分数组的时间是 O(M) 的。
复杂度于是从 O( (N+M) * log M ) 降至 O( M + N*log M),再加之二分里那个O(N)的复杂度的常数要比原来没优化之前的O(M)的小得多(会提前返回0的情况),实测快了4倍不止。
(注:图上的那个07-27是前年做的。。。。)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+5;
inline int read(){
int x=0; char ch=getchar();
for(;!isdigit(ch);ch=getchar());
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
return x;
}
int n,d[N],s[N],t[N];
int r[N],m,R,L,mid,ans,pre;
ll ad[N],now;
inline bool can(){
now=0;
if(mid>pre) for(int i=pre+1;i<=mid;i++) ad[s[i]]+=(ll)d[i],ad[t[i]]-=(ll)d[i];
else for(int i=pre;i>mid;i--) ad[s[i]]-=(ll)d[i],ad[t[i]]+=(ll)d[i];
for(int i=0;i<=n;i++,now+=ad[i]) if(now>r[i]) return 0;
return 1;
}
int main(){
n=read(),R=m=read(),L=1;
for(int i=1;i<=n;i++) r[i]=read();
for(int i=1;i<=m;i++) d[i]=read(),s[i]=read(),t[i]=read()+1;
for(;L<=R;pre=mid){
mid=L+R>>1;
if(can()) ans=mid,L=mid+1;
else R=mid-1;
}
if(ans==m) puts("0");
else printf("-1
%d
",ans+1);
return 0;
}