HDU 4348 To the moon [主席树 区间修改]

来源:互联网 发布:海量 top k算法 编辑:程序博客网 时间:2024/06/05 17:58

题意:给你长度为n的数组,共有四个操作:

1.对区间【L,R】增加d,并时间增加1   

2.询问当前时间的区间【L,R】的和

3.询问时间为T时的区间【L,R】的和

4.返回到时间为T的时候

题解:既然有历史版本,肯定是用主席树了,但是主席树的区间的修改,一种办法是在遇到有延迟更新的区间的时候重新开左右儿子来pushdown 标记,但是这题严格一点的数据就能把他卡成空间为n*n*logn。所以还有一种办法就是,永久化标记,不pushdown,这时候就可以大大节省空间了,nlogn的空间复杂度。

AC代码:

#include<stdio.h>#include<algorithm>#include<map>using namespace std;#define N 100005typedef long long ll;ll a[N];ll tree[N*25],add[N*25];int root[N*25],lchild[N*25],rchild[N*25];int tot;void build(int L,int R,int root){add[root]=0;if(L==R){tree[root]=a[L];return ;}int mid=L+R>>1;build(L,mid,lchild[root]=++tot);build(mid+1,R,rchild[root]=++tot);tree[root]=tree[lchild[root]]+tree[rchild[root]];}void update(int last,int cur,int l,int r,int L,int R,ll k){tree[cur]=tree[last]+(r-l+1)*k;lchild[cur]=lchild[last];rchild[cur]=rchild[last];add[cur]=add[last];if(l<=L&&R<=r){add[cur]+=k;return ;}int mid=L+R>>1;if(r<=mid)update(lchild[last],lchild[cur]=++tot,l,r,L,mid,k);else if(l>mid)update(rchild[last],rchild[cur]=++tot,l,r,mid+1,R,k);else {update(lchild[last],lchild[cur]=++tot,l,mid,L,mid,k);update(rchild[last],rchild[cur]=++tot,mid+1,r,mid+1,R,k);}}ll query(int root,int l,int r,int L,int R,ll ad){if(l<=L&&R<=r)return tree[root]+(r-l+1)*ad;int mid=L+R>>1;if(r<=mid)return query(lchild[root],l,r,L,mid,ad+add[root]);else if(l>mid)return query(rchild[root],l,r,mid+1,R,ad+add[root]);else returnquery(lchild[root],l,mid,L,mid,ad+add[root])+query(rchild[root],mid+1,r,mid+1,R,ad+add[root]);}int main(){int n,m;while(~scanf("%d%d",&n,&m)){tot=0;for(int i=1;i<=n;i++)scanf("%lld",&a[i]);build(1,n,root[1]=++tot);int time=1;for(int i=0;i<m;i++){char op[2];scanf("%s",op);if(op[0]=='C'){int l,r;ll k;scanf("%d%d%lld",&l,&r,&k);time++;update(root[time-1],root[time]=++tot,l,r,1,n,k);}else if(op[0]=='Q'){int l,r;scanf("%d%d",&l,&r);printf("%lld\n",query(root[time],l,r,1,n,0));}else if(op[0]=='H'){int l,r,t;scanf("%d%d%d",&l,&r,&t);t++;printf("%lld\n",query(root[t],l,r,1,n,0));}else if(op[0]=='B'){int t;scanf("%d",&t);time=t+1;}}}}


阅读全文
0 0
原创粉丝点击