区间加的可持久化线段树
懒标记不再适用,将标记永久化,统计答案时累加即可。
#include <set>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <assert.h>
#include <algorithm>
using namespace std;
#define LL long long
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define GO debug("GO\n")
inline int rint() {
register int x = 0, f = 1; register char c;
while (!isdigit(c = getchar())) if (c == '-') f = -1;
while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getchar()));
return x * f;
}
template<typename T> inline void chkmin(T &a, T b) { a > b ? a = b : 0; }
template<typename T> inline void chkmax(T &a, T b) { a < b ? a = b : 0; }
const int maxN = 1e5 + 10, maxM = 2e7;
int n, m, now, a[maxN];
int rt[maxN], cnt;
#define ls(x) (tree[x].ls)
#define rs(x) (tree[x].rs)
struct Node {
int ls, rs;
LL sum, tag;
} tree[maxM];
void Build(int &x, int l, int r) {
x = ++cnt;
if (l == r) {
tree[x].sum = a[l];
return;
}
int mid = (l + r) >> 1;
Build(ls(x), l, mid); Build(rs(x), mid + 1, r);
tree[x].sum = tree[ls(x)].sum + tree[rs(x)].sum;
}
void Add(int last, int &x, int l, int r, int L, int R, int add) {
tree[x = ++cnt] = tree[last];
tree[x].sum += 1ll * (min(R, r) - max(L, l) + 1) * add;
if (L <= l and r <= R) {
tree[x].tag += add;
return;
}
int mid = (l + r) >> 1;
if (L <= mid) Add(ls(last), ls(x), l, mid, L, R, add);
if (mid < R) Add(rs(last), rs(x), mid + 1, r, L, R, add);
}
LL query(int x, int l, int r, int L, int R) {
if (L <= l and r <= R)
return tree[x].sum;
int mid = (l + r) >> 1;
LL res = 0;
if (L <= mid) res += query(ls(x), l, mid, L, R);
if (mid < R) res += query(rs(x), mid + 1, r, L, R);
return res + 1ll * tree[x].tag * (min(R, r) - max(L, l) + 1);
}
signed main() {
n = rint(), m = rint();
for (int i = 1; i <= n; ++ i) a[i] = rint();
Build(rt[0], 1, n);
char op[30];
int a, b, c;
while (m--) {
scanf("%s", op);
switch(op[0]) {
case 'C' :
a = rint(), b = rint(), c = rint(); now++;
Add(rt[now-1], rt[now], 1, n, a, b, c); break;
case 'Q' :
a = rint(), b = rint();
printf("%lld\n", query(rt[now], 1, n, a, b)); break;
case 'H' :
a = rint(), b = rint(), c = rint();
printf("%lld\n", query(rt[c], 1, n, a, b)); break;
case 'B' :
now = rint(); break;
}
}
}