查询历史状态,在线做的话就要用可持久化数据结构,所谓可持久化,意思就是保存所有的历史状态,但是因为每次修改只涉及到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;
}