https://www.luogu.com.cn/problem/P1083
最普通的是线段树做法, 还有差分
写一个 \(O(n+m)\) 的做法
瞎编的名字:可撤销的差分 很好理解
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N= 1e6+ 5;
int a[N], d[N], s[N], t[N], cnt[N];
signed main()
{
int n, m; cin>> n>> m;
for(int i= 1; i<= n; i++ ) scanf("%lld", &a[i]);
for(int i= 1; i<= m; i++ ) scanf("%lld%lld%lld", &d[i], &s[i], &t[i]);
for(int i= 1; i<= n; i++ ) cnt[s[i]]-= d[i], cnt[t[i]+ 1]+= d[i]; //差分
int j= m;
for(int i= 1; i<= n; i++ )
{
cnt[i]+= cnt[i- 1]; //算真实值
while(cnt[i]+ a[i]< 0) //开始撤销
{
if(s[j]<= i&& t[j]>= i) cnt[i]+= d[j], cnt[t[j]+ 1]-= d[j]; //注意特判
else if(s[j]> i) cnt[s[j]]+= d[j], cnt[t[j]+ 1]-= d[j];
j-- ;
}
}
if(j== m) cout<< 0<< endl;
else cout<< -1<< endl<< j+ 1<< endl;
return 0;
}