vp的时候没码出来。。
我们用set去维护, 每一块区域, 每块区域内的元素与下一个元素的差值刚好为ki,每次加值的时候我们暴力合并,
可以发现我们最多合并O(n)次。 然后写个线段树就没了。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ull unsigned long long using namespace std; const int N = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const double PI = acos(-1); int n, q, val[N], k[N]; LL prefix[N]; set<PII> seg; char op[10]; LL a[N << 2], add[N << 2]; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 void push(int rt, int l, int mid, int r) { if(add[rt]) { a[rt << 1] += add[rt] * (mid - l + 1); a[rt << 1 | 1] += add[rt] * (r - mid); add[rt << 1] += add[rt]; add[rt << 1 | 1] += add[rt]; add[rt] = 0; } } void build(int l, int r, int rt) { if(l == r) { a[rt] = val[l]; return; } int mid = l + r >> 1; build(lson); build(rson); a[rt] = a[rt << 1] + a[rt << 1 | 1]; } void update(int L, int R, LL val, int l, int r, int rt) { if(l >= L && r <= R) { a[rt] += val * (r - l + 1); add[rt] += val; return; } int mid = l + r >> 1; push(rt, l, mid, r); if(L <= mid) update(L, R, val, lson); if(R > mid) update(L, R, val, rson); a[rt] = a[rt << 1] + a[rt << 1 | 1]; } LL query(int L, int R, int l, int r, int rt) { if(l >= L && r <= R) return a[rt]; int mid = l + r >> 1; push(rt, l, mid, r); if(R <= mid) return query(L, R, lson); else if(L > mid) return query(L, R, rson); else return query(L, R, lson) + query(L, R, rson); } int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d", &val[i]); prefix[i] = prefix[i - 1] + val[i]; } for(int i = 1; i < n; i++) scanf("%d", &k[i]); for(int i = 1; i <= n; i++) seg.insert(mk(i, i)); build(1, n, 1); scanf("%d", &q); while(q--) { scanf("%s", op); if(op[0] == '+') { int x, v; scanf("%d%d", &x, &v); auto sg = seg.upper_bound(mk(x, inf)); sg--; int L = sg->fi, R = sg->se; seg.erase(sg); if(L <= x - 1) seg.insert(mk(L, x - 1)); update(x, R, v, 1, n, 1); while(R < n) { LL v1 = query(R, R, 1, n, 1); LL v2 = query(R + 1, R + 1, 1, n, 1); if(v1 + k[R] <= v2) break; LL add = v1 + k[R] - v2; auto sg = seg.lower_bound(mk(R + 1, R + 1)); update(sg->fi, sg->se, add, 1, n, 1); R = sg->se; seg.erase(sg); } seg.insert(mk(x, R)); } else { int L, R; scanf("%d%d", &L, &R); printf("%lld ", query(L, R, 1, n, 1)); } } return 0; } /* */