查詢曆史狀態,線上做的話就要用可持久化資料結構,所謂可持久化,意思就是儲存所有的曆史狀態,但是因為每次修改只涉及到logn個節點,所以每次只建立logn個節點。其餘節點及可利用曆史版本的。
但是這個題目如果用lazy的話,因為每次查詢會下放lazy,導致必須建立節點,最後會造成mle。所以用維護兩個值來實現最後的結果。
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn=1e5+9,maxm=2511111;long long a[maxn];int lon,root[maxn*5];struct{ long long x,sum; int l,r,ls,rs;}tr[maxm];int maketree(int l,int r){ int t=++lon; tr[t].l=l; tr[t].r=r; tr[t].x=tr[t].sum=0; if(l==r) return t; int mid=l+r>>1; tr[t].ls=maketree(l,mid); tr[t].rs=maketree(mid+1,r); return t;}void get(int t,int s){ tr[t]=tr[s];}int modify(int t,int x,long long tmp){ int now=++lon; get(now,t); if(tr[now].l==tr[now].r) { tr[now].sum+=tmp; tr[now].x+=(x-1)*tmp; return now; } int mid=tr[t].l+tr[t].r>>1; if(x<=mid) tr[now].ls=modify(tr[now].ls,x,tmp); else tr[now].rs=modify(tr[now].rs,x,tmp); tr[now].sum=tr[tr[now].ls].sum+tr[tr[now].rs].sum; tr[now].x=tr[tr[now].ls].x+tr[tr[now].rs].x; return now;}long long queryx(int t,int l,int r){ if(tr[t].l==l&&tr[t].r==r) return tr[t].x; int mid=tr[t].l+tr[t].r>>1; if(r<=mid) return queryx(tr[t].ls,l,r); else if(mid+1<=l) return queryx(tr[t].rs,l,r); else { long long ret=queryx(tr[t].ls,l,mid); ret+=queryx(tr[t].rs,mid+1,r); return ret; }}long long querysum(int t,int l,int r){ if(tr[t].l==l&&tr[t].r==r) return tr[t].sum; int mid=tr[t].l+tr[t].r>>1; if(r<=mid) return querysum(tr[t].ls,l,r); else if(mid+1<=l) return querysum(tr[t].rs,l,r); else { long long ret=querysum(tr[t].ls,l,mid); ret+=querysum(tr[t].rs,mid+1,r); return ret; }}long long query(int t,int x){ if(x<1) return 0; long long sum=querysum(t,1,x); long long xx=queryx(t,1,x); return sum*x-xx;}void init(){ lon=0;}int main(){// freopen("in.txt","r",stdin); int n,m; while(scanf("%d %d",&n,&m)!=EOF) { for(int i=1;i<=n;i++) { scanf("%I64d",&a[i]); a[i]+=a[i-1]; } init(); int now=0; root[now]=maketree(1,n); for(int i=1;i<=m;i++) { char tmp[5]; scanf("%s",tmp+1); if(tmp[1]=='Q') { int l,r; scanf("%d %d",&l,&r); long long rr=query(root[now],r); long long ll=query(root[now],l-1); long long ans=rr-ll+a[r]-a[l-1]; printf("%I64d\n",ans); } else if(tmp[1]=='C') { int l,r,d; scanf("%d %d %d",&l,&r,&d); int tmp=now; root[++tmp]=modify(root[now],l,d); if(r+1<=n) root[now+2]=modify(root[tmp],r+1,-d); else root[now+2]=root[now+1]; now+=2; } else if(tmp[1]=='H') { int l,r,t; scanf("%d %d %d",&l,&r,&t); long long rr=query(root[t*2],r); long long ll=query(root[t*2],l-1); printf("%I64d\n",rr-ll+a[r]-a[l-1]); } else { int t; scanf("%d",&t); now=t*2; lon=root[now+1]; } }// cout<<lon<<endl; } return 0;}