主席树(普通线段树 标记永久化)模板

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;
} 
posted @ 2022-02-23 15:17  StranGePants  阅读(36)  评论(0编辑  收藏  举报