只说在线做法,可持久化线段树不多说,区间加法 pushdown 不现实,所以考虑标记永久化处理。
但是 AcWing 的数据跟 HDU 数据相比不满足题面所说的回滚状态不会再被访问的特性,所以之前留下的状态不能直接覆盖。
int n, m;
int a[N];
char op;
int l, r, val;
int rt[VER];
struct node
{
int lc, rc;
i64 sum;
int tag_add; // tag limit : M|d| <= 10^9
} tr[(N << 1) + ((VER * (LOG_N + 1)) << 1)];
int cnt, ver;
void init() { ver = cnt = 0; }
int build(int l, int r)
{
int u = ++cnt;
if (l == r)
return tr[u].sum = a[l], u;
int m = (l + r) >> 1;
tr[u].lc = build(l, m), tr[u].rc = build(m + 1, r);
tr[u].sum = tr[tr[u].lc].sum + tr[tr[u].rc].sum;
return u;
}
int new_node(int v)
{
int u = ++cnt;
tr[u] = tr[v];
return u;
}
int _add(int v, int l, int r, int L, int R, int val)
{
if (L > r || R < l) return v;
int u = new_node(v);
tr[u].sum += 1ll * (min(R, r) - max(L, l) + 1) * val;
if (l <= L && R <= r) return tr[u].tag_add += val, u;
int M = (L + R) >> 1;
tr[u].lc = _add(tr[v].lc, l, r, L, M, val);
tr[u].rc = _add(tr[v].rc, l, r, M + 1, R, val);
return u;
}
void add(int now, int pre, int l, int r, int val) { rt[now] = _add(rt[pre], l, r, 1, n, val); }
i64 _sum(int u, int l, int r, int L, int R, i64 delta)
{
if (L > r || R < l) return 0;
if (l <= L && R <= r) return tr[u].sum + delta * (min(R, r) - max(L, l) + 1);
int M = (L + R) >> 1;
return _sum(tr[u].lc, l, r, L, M, delta + tr[u].tag_add) + _sum(tr[u].rc, l, r, M + 1, R, delta + tr[u].tag_add);
}
i64 sum(int now, int l, int r) { return _sum(rt[now], l, r, 1, n, 0); }
int main()
{
while (rd(&n) && rd(&m))
{
init();
for (int i = 1; i <= n; ++i)
rd(&a[i]);
rt[0] = build(1, n);
while (m--)
{
rd_char(&op);
switch (op)
{
case 'C':
rd(&l), rd(&r), rd(&val), ++ver;
add(ver, ver - 1, l, r, val);
break;
case 'Q':
rd(&l), rd(&r);
wr(sum(ver, l, r)), putchar('\n');
break;
case 'H':
rd(&l), rd(&r), rd(&val);
wr(sum(val, l, r)), putchar('\n');
break;
case 'B':
rd(&ver);
break;
default:
break;
}
}
}
}