借教室
阿新 • • 發佈:2021-10-08
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; }