主席树 hdu 4348
题意:有一个由n个数组成的序列,有4中操作:
1.C l r d [l,r]这段区间都加上d
2.Q l r 询问[l,r]这段区间的和
3.H l r t 询问之前t时间[l,r]的区间和
4.B t 回到t时间,且下一秒的时间从t开始
按时间建立主席树,主席树上的每一棵线段树维护[1,n]这段序列的信息,这里成段更新的时候要注意,以往写线段树的时候,都是把lazy标记向下传,但是写主席树的时候每一次下传,那么新的节点数就会非常多,会爆内存,所以我们不把lazy操作下传,只是在询问的时候,最后累加的答案加上每一个父亲节点上的lazy值。
1 #include<cstdio> 2 #include<algorithm> 3 #include<queue> 4 #include<iostream> 5 using namespace std; 6 typedef long long ll; 7 const int maxn=1e5+10; 8 ll a[maxn]; 9 int root[maxn]; 10 struct node 11 { 12 int ln,rn; 13 ll lazy,sum; 14 }tree[maxn*30]; int cnt; 15 void build(int &x,int l,int r) 16 { 17 ++cnt;x=cnt; 18 tree[x].lazy=0; 19 if(l==r){ 20 tree[x].sum=a[l]; 21 return; 22 } 23 int mid=l+r>>1; 24 build(tree[x].ln,l,mid); 25 build(tree[x].rn,mid+1,r); 26 tree[x].sum=tree[tree[x].ln].sum+tree[tree[x].rn].sum; 27 } 28 void update(int &x,int y,int L,int R,int l,int r,int val) 29 { 30 tree[++cnt]=tree[y]; 31 x=cnt; 32 if(L==l&&R==r){ 33 tree[cnt].lazy+=val; 34 tree[cnt].sum+=(R-L+1)*val; 35 return; 36 } 37 tree[x].sum+=(R-L+1)*val; 38 int mid=l+r>>1; 39 if(R<=mid) update(tree[x].ln,tree[y].ln,L,R,l,mid,val); 40 else if(L>mid) update(tree[x].rn,tree[y].rn,L,R,mid+1,r,val); 41 else{ 42 update(tree[x].ln,tree[y].ln,L,mid,l,mid,val); 43 update(tree[x].rn,tree[y].rn,mid+1,R,mid+1,r,val); 44 } 45 } 46 ll query(int root,int L,int R,int l,int r) 47 { 48 ll ans=0; 49 if(l==L&&r==R) return tree[root].sum; 50 ans+=(ll)tree[root].lazy*(ll)(R-L+1); 51 int mid=l+r>>1; 52 if(R<=mid) ans+=query(tree[root].ln,L,R,l,mid); 53 else if(L>mid) ans+=query(tree[root].rn,L,R,mid+1,r); 54 else{ 55 ans+=query(tree[root].ln,L,mid,l,mid); 56 ans+=query(tree[root].rn,mid+1,R,mid+1,r); 57 } 58 return ans; 59 } 60 void init() 61 { 62 cnt=0; 63 } 64 int main() 65 { 66 int n,m; 67 while(scanf("%d%d",&n,&m)!=EOF){ 68 init(); 69 for(int i=1;i<=n;i++) scanf("%lld",&a[i]); 70 int now=0; 71 build(root[0],1,n); 72 char t1[3];int t2,t3,t4; 73 while(m--){ 74 scanf("%s",t1); 75 if(t1[0]=='Q'){ 76 //当前时间线; 77 scanf("%d%d",&t2,&t3); 78 ll ans=query(root[now],t2,t3,1,n); 79 printf("%lld\n",ans); 80 } 81 else if(t1[0]=='C'){ 82 now++; 83 scanf("%d%d%d",&t2,&t3,&t4); 84 update(root[now],root[now-1],t2,t3,1,n,t4); 85 } 86 else if(t1[0]=='H'){ 87 //某个时间线; 88 scanf("%d%d%d",&t2,&t3,&t4); 89 ll ans=query(root[t4],t2,t3,1,n); 90 printf("%lld\n",ans); 91 } 92 else{ 93 //返回某个时间线; 94 scanf("%d",&t2); 95 now=t2; 96 } 97 } 98 } 99 return 0; 100 }