主席树区间修改模板,用了标记永久化。
#include
#include
#define ll long long
using namespace std;
int root[3000010],rs[3000010],ls[3000010],add[3000010];
ll sum[3000010];
int a[3000010],tot;
inline int read()
{
int x=0,flag=1;char c=getchar();
while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
return x*flag;
}
inline void copy(int x,int y)
{
ls[y]=ls[x],rs[y]=rs[x];
sum[y]=sum[x],add[y]=add[x];
}
inline void push_up(int x)
{
sum[x]=sum[ls[x]]+sum[rs[x]];
}
void build(int &root,int l,int r)
{
root=++tot;
sum[root]=ls[root]=rs[root]=add[root]=0;
if(l==r)
{
sum[root]=a[l];
return;
}
int mid=l+r>>1;
build(ls[root],l,mid);
build(rs[root],mid+1,r);
push_up(root);
}
void update(int &root,int pre,int l,int r,int x,int y,int k)
{
root=++tot;
copy(pre,root);
sum[root]+=1ll*(y-x+1)*k;
if(x==l&&y==r)
{
add[root]+=k;
return;
}
int mid=l+r>>1;
if(y<=mid) update(ls[root],ls[pre],l,mid,x,y,k);
else if(x>mid) update(rs[root],rs[pre],mid+1,r,x,y,k);
else
{
update(ls[root],ls[pre],l,mid,x,mid,k);
update(rs[root],rs[pre],mid+1,r,mid+1,y,k);
}
}
ll query(int root,int l,int r,int x,int y)
{
if(x==l&&y==r) return sum[root];
ll ans=1ll*add[root]*(y-x+1);
int mid=l+r>>1;
if(y<=mid) ans+=query(ls[root],l,mid,x,y);
else if(x>mid) ans+=query(rs[root],mid+1,r,x,y);
else
{
ans+=query(ls[root],l,mid,x,mid);
ans+=query(rs[root],mid+1,r,mid+1,y);
}
return ans;
}
int main()
{
int n,m;
while(cin>>n>>m)
{
tot=0;
int now=0,l,r,k;
for(int i=1;i<=n;i++) a[i]=read();
build(root[0],1,n);
while(m--)
{
char s[5];
scanf("%s",s);
if(s[0]=='Q') l=read(),r=read(),cout<1,n,l,r)<<'\n';
else if(s[0]=='C') l=read(),r=read(),k=read(),update(root[now+1],root[now],1,n,l,r,k),now++;
else if(s[0]=='H') l=read(),r=read(),k=read(),cout<1,n,l,r)<<'\n';
else now=read();
}
}
return 0;
}