题目大意:
给一个序列,4种操作:
- C l r x 时间戳++,并把[l, r]区间内的数都加一。
- Q l r 询问当前时间戳的[l, r]区间和。
- H l r x 询问x时间戳的[l, r]区间和。
- B x 将当前时间戳更改为x。
做法:
做法就是主席树,每次更改的时候新建一颗线段树,并且维护一个lazy tag即可。
/*************************************************************
Problem: hdu 4348 To the moon
User: fengyuan
Language: C++
Result: Accepted
Time: 280 ms
Memory: 56.4 MB
Submit_Time: 2017-12-03 17:26:22
*************************************************************/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cctype>
#include<vector>
#include<map>
#include<queue>
#define rep(i, x, y) for (int i = (x); i <= (y); i ++)
#define down(i, x, y) for (int i = (x); i >= (y); i --)
#define mid ((l+r)/2)
#define lc (o<<1)
#define rc (o<<1|1)
#define pb push_back
#define mp make_pair
#define PII pair<int, int>
#define F first
#define S second
#define B begin()
#define E end()
using namespace std;
typedef long long LL;
//head
const int N = 100005, M = 3000010;
int n, m, tot, clk;
int a[N], T[N], L[M], R[M], add[M];
LL sum[M];
inline void pushup(int rt)
{
sum[rt] = sum[L[rt]] + sum[R[rt]];
}
inline int build(int l, int r)
{
int rt = ++ tot;
if (l == r){
L[rt] = 0; R[rt] = 0;
sum[rt] = a[l];
return rt;
}
L[rt] = build(l, mid);
R[rt] = build(mid+1, r);
pushup(rt);
return rt;
}
inline int insert(int pre, int l, int r, int x, int y, int w)
{
int rt = ++ tot;
L[rt] = L[pre]; R[rt] = R[pre]; add[rt] = add[pre]; sum[rt] = sum[pre];
sum[rt] += 1LL*w*(y-x+1);
if (l == x && r == y){
add[rt] += w;
return rt;
}
if (y <= mid) L[rt] = insert(L[pre], l, mid, x, y, w);
else if (x > mid) R[rt] = insert(R[pre], mid+1, r, x, y, w);
else L[rt] = insert(L[pre], l, mid, x, mid, w), R[rt] = insert(R[pre], mid+1, r, mid+1, y, w);
return rt;
}
inline LL query(int o, int l, int r, int x, int y)
{
if (l == x && r == y) return sum[o];
LL ret = 1LL*add[o]*(y-x+1);
if (y <= mid) return ret + query(L[o], l, mid, x, y);
else if (x > mid) return ret + query(R[o], mid+1, r, x, y);
else return ret + query(L[o], l, mid, x, mid) + query(R[o], mid+1, r, mid+1, y);
}
int main()
{
bool flag = false;
while (~scanf("%d%d", &n, &m)){
if (flag) puts("");
flag = true;
rep(i, 1, n) scanf("%d", &a[i]);
tot = 0;
memset(T, 0, sizeof T);
memset(sum, 0, sizeof sum);
memset(add, 0, sizeof add);
T[0] = build(1, n); clk = 0;
while (m --){
char ch[3]; int l, r, x;
scanf("%s", ch);
if (ch[0] == 'C'){
scanf("%d%d%d", &l, &r, &x);
clk ++;
T[clk] = insert(T[clk-1], 1, n, l, r, x);
} else if (ch[0] == 'Q'){
scanf("%d%d", &l, &r);
printf("%lld\n", query(T[clk], 1, n, l, r));
} else if (ch[0] == 'H'){
scanf("%d%d%d", &l, &r, &x);
printf("%lld\n", query(T[x], 1, n, l, r));
} else scanf("%d", &clk);
}
}
return 0;
}