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;
}

未来可期。