题目:给你N个数,M个操作,操作有4种类型,C l r d 将区间[l,r]加上d,Q l r 询问区间[l,r]的和,H l r t询问时间t的区间[l,r]的和,B t回到时间t,初始时时间是0,每进行一次C操作,时间加1
思路:主席树,注意lazy标记下传会产生大量的空间,内存不够,因此lazy直接放在节点上就好了,查询的时候加上去就行了
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<numeric>
using namespace std;
#define PI acos(-1.0)
#define LL long long
#define ULL unsigned long long
#define INF 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define PP puts("*********************");
template<class T> T f_abs(T a){ return a > 0 ? a : -a; }
template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
// 0x3f3f3f3f3f3f3f3f
// 0x3f3f3f3f
const int maxn=1e5+50;
const int maxm=maxn*30;
int root[maxn],lson[maxm],rson[maxm],lazy[maxm];
LL sum[maxm];
int tot;
int arr[maxn];
int build(int l,int r){
int rt=tot++;
lazy[rt]=0;
if(l==r){
sum[rt]=arr[l];
return rt;
}
int mid=(l+r)/2;
lson[rt]=build(l,mid);
rson[rt]=build(mid+1,r);
sum[rt]=sum[lson[rt]]+sum[rson[rt]];
return rt;
}
int update(int rt,int l,int r,int L,int R,int val){
int newrt=tot++;
lazy[newrt]=lazy[rt];
if(L<=l&&r<=R){
lazy[newrt]+=val;
sum[newrt]=sum[rt]+(LL)(r-l+1)*val;
lson[newrt]=lson[rt];
rson[newrt]=rson[rt];
return newrt;
}
int mid=(l+r)/2;
if(R<=mid){
lson[newrt]=update(lson[rt],l,mid,L,R,val);
rson[newrt]=rson[rt];
}
else if(L>mid){
lson[newrt]=lson[rt];
rson[newrt]=update(rson[rt],mid+1,r,L,R,val);
}
else{
lson[newrt]=update(lson[rt],l,mid,L,R,val);
rson[newrt]=update(rson[rt],mid+1,r,L,R,val);
}
sum[newrt]=sum[lson[newrt]]+sum[rson[newrt]]+(LL)lazy[newrt]*(r-l+1);
return newrt;
}
LL ans;
void query(int rt,int l,int r,int L,int R,int val){
if(L<=l&&r<=R){
ans+=sum[rt]+(LL)val*(r-l+1);
return;
}
int mid=(l+r)/2;
if(L<=mid) query(lson[rt],l,mid,L,R,val+lazy[rt]);
if(R>mid) query(rson[rt],mid+1,r,L,R,val+lazy[rt]);
}
int main(){
int n,m,l,r,d,t;
char str[20];
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;i++)
scanf("%d",&arr[i]);
int now=0;
tot=0;
root[now]=build(1,n);
while(m--){
scanf("%s",str);
if(str[0]=='C'){
scanf("%d%d%d",&l,&r,&d);
now++;
root[now]=update(root[now-1],1,n,l,r,d);
}
else if(str[0]=='Q'){
scanf("%d%d",&l,&r);
ans=0;
query(root[now],1,n,l,r,0);
printf("%lld\n",ans);
}
else if(str[0]=='H'){
scanf("%d%d%d",&l,&r,&d);
ans=0;
query(root[d],1,n,l,r,0);
printf("%lld\n",ans);
}
else{
scanf("%d",&t);
now=t;
}
}
}
return 0;
}