【HDU - 4348】To the moon(主席树在线区间更新)
BUPT2017 wintertraining(15) #8G
题意
给一个数组a,有n个数,m次操作。\(N, M ≤ 10^5, |A i| ≤ 10^9, 1 ≤ l ≤ r ≤ N, |d| ≤ 10^4\)
操作有四种,
C l r d:更新区间[l,r],值都加上d,并且时间前进1
Q l r:查询[l,r]的区间和
H l r t:查询t时刻的区间和
B t:回到t时刻(一定是历史时刻),且t时刻之后的操作都作废了。
题解
这道题的关键是怎么更新区间和。
本来线段树更新区间和要push down也就是把懒惰标记下移,但是这样,整个修改区间都需要新建线段树的节点,空间不够。
所以考虑在查询的时候传参数下去,也就是一路加上大区间的lazy值,这样就不用push down了。
代码
#include <cstdio>
#include <cstring>
#define N 100005
#define M (N*25)
typedef long long ll;
namespace PST{
int T[N],lson[M],rson[M],tot,n;
ll sum[M], lz[M];
void init(int _n){
tot=0;
n=_n;
memset(sum,0,sizeof sum);
memset(lz,0,sizeof lz);
}
void push_up(int root,int l,int r){
sum[root]=sum[lson[root]]+sum[rson[root]]+lz[root]*(r-l+1);
}
int build(int l,int r){
int root=++tot;
if(l==r){
scanf("%lld",sum+tot);
return tot;
}
int mid=l+r>>1;
lson[root]=build(l,mid);
rson[root]=build(mid+1,r);
push_up(root,l,r);
return root;
}
int update(int root,int l,int r,int L,int R,int val){
int newroot=++tot;
lson[newroot]=lson[root];
rson[newroot]=rson[root];
lz[newroot]=lz[root];
if(L<=l&&r<=R){
sum[newroot]=sum[root]+(ll)val*(r-l+1);
lz[newroot]+=val;
return newroot;
}
int mid=l+r>>1;
if(L<=mid)
lson[newroot]=update(lson[root],l,mid,L,R,val);
if(R>mid)
rson[newroot]=update(rson[root],mid+1,r,L,R,val);
push_up(newroot,l,r);
return newroot;
}
ll query(int root,int l,int r,int L,int R,ll add){
if(L<=l&&r<=R){
return sum[root]+(add)*(r-l+1);
}
int mid=l+r>>1;
ll ans=0;
if(L<=mid)
ans+=query(lson[root],l,mid,L,R,lz[root]+add);
if(R>mid)
ans+=query(rson[root],mid+1,r,L,R,lz[root]+add);
return ans;
}
}
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
int now;
PST::init(n);
PST::T[now=0]=PST::build(1,n);
for(int i=0;i<m;++i){
char op;
int l,r,t,d;
scanf(" %c",&op);
if(op=='Q'){
scanf("%d%d",&l,&r);
printf("%lld\n",PST::query(PST::T[now],1,n,l,r,PST::lz[PST::T[now]]));
}else if(op=='H'){
scanf("%d%d%d",&l,&r,&t);
printf("%lld\n",PST::query(PST::T[t],1,n,l,r,PST::lz[PST::T[t]]));
}else if(op=='B'){
scanf("%d", &now);
PST::tot=PST::T[now+1]-1;
}else if(op=='C'){
scanf("%d%d%d",&l,&r,&d);
int tmp=now;
PST::T[++now]=PST::update(PST::T[tmp],1,n,l,r,d);
}
}
}
}
┆凉┆暖┆降┆等┆幸┆我┆我┆里┆将┆ ┆可┆有┆谦┆戮┆那┆ ┆大┆始┆ ┆然┆
┆薄┆一┆临┆你┆的┆还┆没┆ ┆来┆ ┆是┆来┆逊┆没┆些┆ ┆雁┆终┆ ┆而┆
┆ ┆暖┆ ┆如┆地┆站┆有┆ ┆也┆ ┆我┆ ┆的┆有┆精┆ ┆也┆没┆ ┆你┆
┆ ┆这┆ ┆试┆方┆在┆逃┆ ┆会┆ ┆在┆ ┆清┆来┆准┆ ┆没┆有┆ ┆没┆
┆ ┆生┆ ┆探┆ ┆最┆避┆ ┆在┆ ┆这┆ ┆晨┆ ┆的┆ ┆有┆来┆ ┆有┆
┆ ┆之┆ ┆般┆ ┆不┆ ┆ ┆这┆ ┆里┆ ┆没┆ ┆杀┆ ┆来┆ ┆ ┆来┆