题目链接:TTM - To the moon
区间修改的主席树。
总所周知,主席树区间修改只能标记永久化。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10,M=N*40;
int rt[N],sum[M],ls[M],rs[M],add[M],tim,cnt,n,m; string op;
void build(int &p,int l,int r){
p=++cnt; if(l==r){cin>>sum[p]; return ;}
int mid=l+r>>1;
build(ls[p],l,mid); build(rs[p],mid+1,r);
sum[p]=sum[ls[p]]+sum[rs[p]];
}
void change(int l,int r,int &x,int y,int ql,int qr,int v){
x=++cnt; sum[x]=sum[y],ls[x]=ls[y],rs[x]=rs[y],add[x]=add[y];
if(ql==l&&qr==r){add[x]+=v; return;} int mid=l+r>>1;
if(qr<=mid) change(l,mid,ls[x],ls[y],ql,qr,v);
else if(ql>mid) change(mid+1,r,rs[x],rs[y],ql,qr,v);
else change(l,mid,ls[x],ls[y],ql,mid,v),change(mid+1,r,rs[x],rs[y],mid+1,qr,v);
sum[x]=sum[ls[x]]+sum[rs[x]]+(mid-l+1)*add[ls[x]]+(r-mid)*add[rs[x]];
}
int ask(int l,int r,int x,int ql,int qr){
if(l==ql&&r==qr) return sum[x]+add[x]*(r-l+1);
int v=(qr-ql+1)*add[x],mid=l+r>>1;
if(qr<=mid) return v+ask(l,mid,ls[x],ql,qr);
else if(ql>mid) return v+ask(mid+1,r,rs[x],ql,qr);
else return ask(l,mid,ls[x],ql,mid)+ask(mid+1,r,rs[x],mid+1,qr)+v;
}
signed main(){
ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
cin>>n>>m; build(rt[0],1,n);
while(m--){
cin>>op; int l,r,x;
if(op[0]=='B') cin>>tim;
if(op[0]=='C') cin>>l>>r>>x,tim++,change(1,n,rt[tim],rt[tim-1],l,r,x);
if(op[0]=='Q') cin>>l>>r,cout<<ask(1,n,rt[tim],l,r)<<'\n';
if(op[0]=='H') cin>>l>>r>>x,cout<<ask(1,n,rt[x],l,r)<<'\n';
}
return 0;
}