题面

解题思路

可持久化线段树

分析

这里只是提供可持久化线段树的板子,思想和主席树类似,每次对 lognlogn 个点进行修改,这样就需要 nlognnlogn 的空间,因此写成结构体,大小开成 80n80n ,反正只要不 MLEMLE 往大了开就好

struct node{
int ls,rs;
LL sum,tag;
}T[N*160];//80应该也是正确的

warning

要注意的地方是标记永久化,不仅要标记永久化,而且 T[root].sumT[root].sum 的值也要做一定修改(比如 rootroot 这个区间完全包含修改区间的时候)

Code

#include<bits/stdc++.h>//大致上和主席树类似,emmm...貌似主席树就是可持久化线段树...
#define rgt register
#define rint rgt int
#define LL long long
#define rll rgt LL
#define inf 0x7f7f7f7f
#define N 100003
using namespace std;
template<class K>inline bool cmax(K&a,const K&b){return(a<b)?a=b,1:0;}
template<class K>inline bool cmin(K&a,const K&b){return(a>b)?a=b,1:0;}
inline LL read() {
rll s=0,p=0;
rgt char c=getchar();
while(!isdigit(c)) p=(c=='-'),c=getchar();
while(isdigit(c)) s=(s<<1)+(s<<3)+c-'0',c=getchar();
return p?-s:s;
}
inline void getc(char&c) {
c=getchar();while(c<'A'||c>'Z') c=getchar();
}
struct node{
int ls,rs;
LL sum,tag;
}T[N*160];
int n,m,L,R,t,res,a[N],root[N];LL w,ans;
inline void built(rint k,rint l,rint r) {
cmax(t,k);
if(l==r) {T[k].sum=a[l];return;}
rint m=(l+r)>>1,ls=k<<1;
built(T[k].ls=ls,l,m),built(T[k].rs=ls|1,m+1,r),
T[k].sum=T[ls].sum+T[ls|1].sum;
}
inline void Modify(rint l,rint r,rint &x,rint y) {
if(r<L||R<l) return;
x=++t,T[t]=T[y];
if(L<=l&&r<=R) {T[x].tag+=w;return;}
T[t].sum+=w*(min(r,R)-max(l,L)+1);//划重点,标记永久化的影响
rint m=(l+r)>>1;
Modify(l,m,T[x].ls,T[y].ls),
Modify(m+1,r,T[x].rs,T[y].rs);
}
inline void push(rll tag,rint l,rint r) {
ans+=(min(R,r)-max(L,l)+1)*tag;
}
inline void Query(rint l,rint r,rint root) {
if(r<L||R<l) return;
if(T[root].tag) push(T[root].tag,l,r);//划重点,标记永久化的影响
if(L<=l&&r<=R) {ans+=T[root].sum;return;}
rint m=(l+r)>>1;
Query(l,m,T[root].ls),Query(m+1,r,T[root].rs);
}
int main()
{
rint i;char op;
n=read(),m=read();
for(i=1;i<=n;i++) a[i]=read();
built(1,1,n),root[0]=1;
while(m--) {
getc(op);
if(op=='C') {
L=read(),R=read(),w=read(),++res;
Modify(1,n,root[res],root[res-1]);
}
else if(op=='Q')
ans=0,L=read(),R=read(),Query(1,n,root[res]),printf("%lld\n",ans);
else if(op=='H')
ans=0,L=read(),R=read(),Query(1,n,root[read()]),printf("%lld\n",ans);
else res=read();
}
return 0;
}

devil.