题解:
因为卡空间,所以直接到spoj上面去做了
区间修改的线段树
但是加lazy会把之前的操作修改
正确的解法是lazy不下传,只是在当前计算
但是听说可以记录时间的下传,我弱弱不会
代码:
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; const int N=100005; typedef long long ll; struct aa { int lc,rc,l,r; ll add,sum; int len(){return r-l+1;} }a[N*200]; int n,m,rt[N],time,tot,Time[N]; void build(int &u,int l,int r) { u=++tot; a[u].l=l,a[u].r=r; if (l==r) {scanf("%lld",&a[u].sum);return;} int mid=(l+r)>>1; build(a[u].lc,l,mid); build(a[u].rc,mid+1,r); a[u].sum=a[a[u].lc].sum+a[a[u].rc].sum; } void insert(int &now,int old,int l,int r,ll d) { now=++tot; a[now]=a[old]; if (a[old].l==l&&a[old].r==r) { a[now].add+=d; return; } a[now].sum+=d*(r-l+1); int mid=(a[now].l+a[now].r)>>1; if (r<=mid) insert(a[now].lc,a[old].lc,l,r,d); else if (mid<l) insert(a[now].rc,a[old].rc,l,r,d); else { insert(a[now].lc,a[old].lc,l,mid,d); insert(a[now].rc,a[old].rc,mid+1,r,d); } } ll query(int u,int l,int r) { ll tmp=a[u].add*(r-l+1); if (a[u].l==l&&a[u].r==r) return a[u].sum+tmp; int mid=(a[u].l+a[u].r)>>1; if (r<=mid) return tmp+query(a[u].lc,l,r); else if (mid<l) return tmp+query(a[u].rc,l,r); return tmp+query(a[u].lc,l,mid)+query(a[u].rc,mid+1,r); } int main() { scanf("%d%d",&n,&m); build(rt[0],1,n); time=0; char ch[2]; int x,y,t;ll d; for (int i=1;i<=m;i++) { scanf("%s",ch); if (ch[0]=='C') { scanf("%d%d%lld",&x,&y,&d); time++; insert(rt[time],rt[time-1],x,y,d); Time[time]=tot; } if (ch[0]=='Q') { scanf("%d%d",&x,&y); printf("%lld\n",query(rt[time],x,y)); } if (ch[0]=='H') { scanf("%d%d%d",&x,&y,&t); printf("%lld\n",query(rt[t],x,y)); } if (ch[0]=='B') { scanf("%d",&time); tot=Time[time]; } } return 0; }