题目链接:
题意
有长度一个为n的数组和m次询问,每次询问为一下四种操作中的一种,初始时间t=0。
C l r d: 第(t+1)个版本[l,r]内的数全部加d。
Q l r:输出当前版本[l,r]内的区间和。
H l r t:输出第t个版本[l,r]内的区间和。
B t:回到第t个版本,也就是说当前版本变成第t个版本。
样例:
输入
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4
2 4
0 0
C 1 1 1
C 2 2 -1
Q 1 2
H 1 2 1
输出
4
55
9
15
0
1
思路:
对于区间修改,需要新开一个root,然后懒标记是不下传的,当搜到带有懒标记的节点时,直接在答案里加上 查询区间长度*懒标记的值。
代码:
//http://acm.hdu.edu.cn/showproblem.php?pid=4348
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const int M=60*N;
int n,m;
int root[N],a[N];
int lch[M],rch[M];
ll sum[M],lazy[M],tot=0;
void init(){
for(int i=1;i<=tot;i++){
lazy[i]=0;
sum[i]=0;
lch[i]=rch[i]=0;
}
tot=0;
}
void build(int &u,int l,int r){
u=++tot;
if(l==r){
sum[u]=a[l];
return ;
}
int mid=(l+r)>>1;
build(lch[u],l,mid);
build(rch[u],mid+1,r);
sum[u]=sum[lch[u]]+sum[rch[u]];
}
void cpy(int from,int to){
lch[to]=lch[from];
rch[to]=rch[from];
sum[to]=sum[from];
lazy[to]=lazy[from];
}
void insert(int &u,int old,int L,int R,int l,int r,int x){
u=++tot;
cpy(old,u);
sum[u]+=(ll)(r-l+1)*x;
if(L==l&&R==r){
lazy[u]+=x;
return;
}
int mid=(L+R)>>1;
if(r<=mid)
insert(lch[u],lch[u],L,mid,l,r,x);
else if(l<=mid){
insert(lch[u],lch[u],L,mid,l,mid,x);
insert(rch[u],rch[u],mid+1,R,mid+1,r,x);
}
else
insert(rch[u],rch[u],mid+1,R,l,r,x);
}
ll query(int u,int L,int R,int l,int r){
ll ans=lazy[u]*(r-l+1);
if(L==l&&R==r){
return sum[u];
}
int mid=(L+R)>>1;
if(r<=mid)
ans+=query(lch[u],L,mid,l,r);
else if(l<=mid){
ans+=query(lch[u],L,mid,l,mid);
ans+=query(rch[u],mid+1,R,mid+1,r);
}
else
ans+=query(rch[u],mid+1,R,l,r);
return ans;
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
init();
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
build(root[0],1,n);
char op[2];
int l,r,d,tt;
int now=0;
ll res;
while(m--){
scanf("%s",op);
if(*op=='C'){
scanf("%d%d%d",&l,&r,&d);
now++;
insert(root[now],root[now-1],1,n,l,r,d);
}
else if(*op=='Q'){
scanf("%d%d",&l,&r);
res=query(root[now],1,n,l,r);
printf("%lld\n",res);
}
else if(*op=='H'){
scanf("%d%d%d",&l,&r,&tt);
res=query(root[tt],1,n,l,r);
printf("%lld\n",res);
}
else{
scanf("%d",&tt);
now=tt;
}
}
}
}