题意:n个数, m个操作
1. C l r d 给[l, r]区间的每个数加上d
2. Q l r: 查询[l, r]区间的和
3. H l r t: 查询第t个操作时[l, r]区间的和
4. B t: 回到第t个操作之后
因为有查询历史的区间和,故用主席树(保留了历史)
区间更新直接更新到每个子节点即可
#define lson l, m
#define rson m+1, r
const int N=1e5+5;
const double eps=1e-8;
int L[N<<5], R[N<<5], sum[N<<5];
LL ans[N<<5];
int tot;
int a[N], T[N], Hash[N];
void pushup(int rt)
{
ans[rt]=ans[L[rt]]+ans[R[rt]];
}
int build(int l, int r)
{
int rt=(++tot);
sum[rt]=0;
if(l==r)
{
scanf("%I64d", &ans[rt]);
L[rt]=R[rt]=0;
return rt;
}
int m=(l+r)>>1;
L[rt]=build(lson);
R[rt]=build(rson);
pushup(rt);
return rt;
}
int update(int pre, int _L, int _R, int l, int r, LL x)
{
int rt=(++tot);
L[rt]=L[pre], R[rt]=R[pre], sum[rt]=sum[pre], ans[rt]=ans[pre]+x*(_R-_L+1);
if(_L<=l && r<=_R)
{
sum[rt]+=x;
return rt;
}
int m=(l+r)>>1;
if(_R<=m)
L[rt]=update(L[pre], _L, _R, lson, x);
else if(_L>m)
R[rt]=update(R[pre], _L, _R, rson, x);
else
{
L[rt]=update(L[rt], _L, m, lson, x);
R[rt]=update(R[rt], m+1, _R, rson, x);
}
return rt;
}
LL query(int rt, int _L, int _R, int l, int r)
{
LL cnt=sum[rt]*(LL)(_R-_L+1);
if(_L<=l && r<=_R)
return ans[rt];
int m=(l+r)>>1;
if(_R<=m)
cnt+=query(L[rt], _L, _R, lson);
else if(_L>m)
cnt+=query(R[rt], _L, _R, rson);
else
{
cnt+=query(L[rt], _L, m, lson);
cnt+=query(R[rt], m+1, _R, rson);
}
return cnt;
}
int main()
{
int n, m;
while(~scanf("%d%d", &n, &m))
{
tot=0;
T[0]=build(1, n);
int time=0;
while(m--)
{
char op[5];
scanf("%s", op);
if(op[0]=='Q')
{
int l, r;
scanf("%d%d", &l, &r);
printf("%I64d\n", query(T[time], l, r, 1, n));
}
else if(op[0]=='C')
{
int l, r;
LL x;
scanf("%d%d%I64d", &l, &r, &x);
T[time+1]=update(T[time++], l, r, 1, n, x);
}
else if(op[0]=='H')
{
int l, r, rt;
scanf("%d%d%d", &l, &r, &rt);
printf("%I64d\n", query(T[rt], l, r, 1, n));
}
else
scanf("%d", &time);
}
}
return 0;
}
HDOJ 4348