主席树(普通线段树 标记永久化)模板
To The Moon
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define ll long long
const int MAXN=1e5+5;
int n,m,cnt,rt[MAXN],now;
ll a[MAXN],sum[MAXN*30],laz[MAXN*30],LL[MAXN*30],RR[MAXN*30];
int build(int p,int L,int R){
p=++cnt;
if(L==R){sum[p]=a[L];return p;}
int mid=(L+R)>>1;
LL[p]=build(LL[p],L,mid);RR[p]=build(RR[p],mid+1,R);sum[p]=sum[LL[p]]+sum[RR[p]];return p;
}
int update(int p,int l,int r,int L,int R,int x){
int pp=++cnt;
sum[pp]=sum[p];LL[pp]=LL[p];RR[pp]=RR[p];laz[pp]=laz[p];
sum[pp]+=(ll)(min(r,R)-max(l,L)+1)*x;
if(l>=L&&r<=R){laz[pp]+=x;return pp;}
int mid=(l+r)>>1;
if(L<=mid) LL[pp]=update(LL[pp],l,mid,L,R,x);
if(R>mid) RR[pp]=update(RR[pp],mid+1,r,L,R,x);
return pp;
}
ll query(int p,int l,int r,int L,int R){
if(l>=L&&r<=R) return sum[p];
ll res=(ll)(min(r,R)-max(l,L)+1)*laz[p];
int mid=(l+r)>>1;
if(L<=mid) res+=query(LL[p],l,mid,L,R);
if(R>mid) res+=query(RR[p],mid+1,r,L,R);
return res;
}
void init(){now=0;
memset(sum,0,sizeof(sum));memset(laz,0,sizeof(laz));
cnt=0;memset(rt,0,sizeof(rt));
}
int main(){
while(~scanf("%d%d",&n,&m)){
init();
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
rt[0]=build(1,1,n);
char s;
for(int i=1;i<=m;i++){scanf(" %c",&s);
if(s=='C'){int L,R;ll x;scanf("%d%d%lld",&L,&R,&x);rt[now+1]=update(rt[now],1,n,L,R,x);now++;}
if(s=='Q'){int L,R;scanf("%d%d",&L,&R);printf("%lld\n",query(rt[now],1,n,L,R));}
if(s=='H'){int L,R,x;scanf("%d%d%d",&L,&R,&x);printf("%lld\n",query(rt[x],1,n,L,R));}
if(s=='B'){int x;scanf("%d",&x);now=x;}
}
}
return 0;
}
本文来自博客园,作者:{StranGePants},转载请注明原文链接:https://www.cnblogs.com/StranGePants/p/15927572.html