主席树 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 }

 

posted @ 2019-10-13 18:02  古比  阅读(119)  评论(0编辑  收藏  举报