傳送門html
題意:c++
一個長度爲n的數組,4種操做 :git
(1)C l r d:區間[l,r]中的數都加1,同時當前的時間戳加1 。數組
(2)Q l r:查詢當前時間戳區間[l,r]中全部數的和 。ui
(3)H l r t:查詢時間戳t區間[l,r]的和 。spa
(4)B t:將當前時間戳置爲t 。code
全部操做均合法 。htm
題解blog
原來……主席樹真的能作可持久化的啊……花了一個下午才搞明白……(雖然是看題解的)get
先考慮一下,若是直接每一次修改的話,一共要修改$r-l+1$次,空間複雜度絕對爆炸
而後考慮一下線段樹的打懶標記,可不能夠套到主席樹上來?
咱們發現能夠這麼作,因而每一次修改區間時,若是區間相等,直接打上標記,等到查詢的時候,再把標記給加上去
ps:更改時間的時候能夠直接把$cnt$改爲$rt[t+1]-1$,這樣的話能夠回收空間
1 //minamoto 2 #include<bits/stdc++.h> 3 #define ll long long 4 using namespace std; 5 const int N=100005,M=N*30; 6 int n,m,cnt,rt[N]; 7 int L[M],R[M];ll sum[M],add[M]; 8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 9 char buf[1<<21],*p1=buf,*p2=buf; 10 inline ll read(){ 11 #define num ch-'0' 12 char ch;bool flag=0;ll res; 13 while(!isdigit(ch=getc())) 14 (ch=='-')&&(flag=true); 15 for(res=num;isdigit(ch=getc());res=res*10+num); 16 (flag)&&(res=-res); 17 #undef num 18 return res; 19 } 20 void build(int &now,int l,int r){ 21 add[now=++cnt]=0; 22 if(l==r) return (void)(sum[now]=read()); 23 int mid=(l+r)>>1; 24 build(L[now],l,mid); 25 build(R[now],mid+1,r); 26 sum[now]=sum[L[now]]+sum[R[now]]; 27 } 28 void update(int last,int &now,int l,int r,int ql,int qr,int x){ 29 now=++cnt; 30 L[now]=L[last],R[now]=R[last],add[now]=add[last],sum[now]=sum[last]; 31 sum[now]+=1ll*x*(qr-ql+1); 32 if(ql==l&&qr==r) return (void)(add[now]+=x); 33 int mid=(l+r)>>1; 34 if(qr<=mid) update(L[last],L[now],l,mid,ql,qr,x); 35 else if(ql>mid) update(R[last],R[now],mid+1,r,ql,qr,x); 36 else return (void)(update(L[last],L[now],l,mid,ql,mid,x),update(R[last],R[now],mid+1,r,mid+1,qr,x)); 37 } 38 ll query(int now,int l,int r,int ql,int qr){ 39 if(l==ql&&r==qr) return sum[now]; 40 int mid=(l+r)>>1; 41 ll res=1ll*add[now]*(qr-ql+1); 42 if(qr<=mid) res+=query(L[now],l,mid,ql,qr); 43 else if(ql>mid) res+=query(R[now],mid+1,r,ql,qr); 44 else res+=query(L[now],l,mid,ql,mid)+query(R[now],mid+1,r,mid+1,qr); 45 return res; 46 } 47 int main(){ 48 //freopen("testdata.in","r",stdin); 49 n=read(),m=read(); 50 cnt=-1; 51 build(rt[0],1,n); 52 int now=0; 53 while(m--){ 54 char ch;int l,r,x; 55 while(!isupper(ch=getc())); 56 switch(ch){ 57 case 'C':{ 58 l=read(),r=read(),x=read(); 59 ++now; 60 update(rt[now-1],rt[now],1,n,l,r,x); 61 break; 62 } 63 case 'Q':{ 64 l=read(),r=read(); 65 printf("%lld\n",query(rt[now],1,n,l,r)); 66 break; 67 } 68 case 'H':{ 69 l=read(),r=read(),x=read(); 70 printf("%lld\n",query(rt[x],1,n,l,r)); 71 break; 72 } 73 case 'B':{ 74 now=read(); 75 cnt=rt[now+1]-1; 76 break; 77 } 78 } 79 } 80 return 0; 81 }