spoj To The Moon

题意:

  带询问历史版本的线段树>_<

解法:

  主席树的成段更新,除了线段树成段更新的懒惰标记之外还要用一个懒惰标记来记录当前节点和其子节点是否是同一个版本的,如果不是的话,在pushdown的过程中要新建两个新节点,别的没什么了>_<

  p.s.主席树的内存消耗真是叹为观止。。。hdu4348徘徊在MLE和RE之间。。。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int N = (int)1e7;
  7 typedef long long ll;
  8 int lson[N],rson[N];
  9 int Time[N],add[N];
 10 bool mark[N];
 11 ll sum[N];
 12 int total;
 13 void pushup(int root){
 14     sum[root] = sum[lson[root]] + sum[rson[root]];
 15 }
 16 void copy(int x,int y){
 17     add[x] = add[y];
 18     sum[x] = sum[y];
 19     lson[x] = lson[y];
 20     rson[x] = rson[y];
 21 }
 22 void pushdown(int root,int L,int R){
 23     if(mark[root]){
 24         int now = ++total;
 25         copy(now,lson[root]);
 26         lson[root] = now;
 27         now = ++total;
 28         copy(now,rson[root]);
 29         rson[root] = now;
 30         mark[lson[root]] = mark[rson[root]] = 1;
 31         mark[root] = 0;
 32     }
 33     if(add[root]){
 34         int m=(L+R)>>1;
 35         add[lson[root]] += add[root];
 36         sum[lson[root]] += 1LL*add[root]*(m-L+1);
 37         add[rson[root]] += add[root];
 38         sum[rson[root]] += 1LL*add[root]*(R-m);
 39         add[root] = 0;
 40     }
 41 }
 42 int build(int L,int R){
 43     int now = ++total;
 44     add[now] = 0;
 45     mark[now] = 0;
 46     if(L==R){
 47         cin>>sum[now];
 48         lson[now] = rson[now] = 0;
 49         return now;
 50     }
 51     int m=(L+R)>>1;
 52     lson[now] = build(L,m);
 53     rson[now] = build(m+1,R);
 54     pushup(now);
 55     return now;
 56 }
 57 int update(int root,int L,int R,int d,int l,int r){
 58     int now = ++total;
 59     if(L==l&&R==r){
 60         add[now] = add[root] + d;
 61         sum[now] = sum[root] + 1LL*d*(r-l+1);
 62         lson[now] = lson[root];
 63         rson[now] = rson[root];
 64         mark[now] = (L!=R);
 65         return now;
 66     }
 67     mark[now] = add[now] = sum[now] = 0;
 68     pushdown(root,l,r);
 69     int m=(l+r)>>1;
 70     if(R<=m){
 71         lson[now] = update(lson[root],L,R,d,l,m);
 72         rson[now] = rson[root];
 73     }else if(L>m){
 74         lson[now] = lson[root];
 75         rson[now] = update(rson[root],L,R,d,m+1,r);
 76     }else{
 77         lson[now] = update(lson[root],L,m,d,l,m);
 78         rson[now] = update(rson[root],m+1,R,d,m+1,r);
 79     }
 80     pushup(now);
 81     return now;
 82 }
 83 ll query(int root,int L,int R,int l,int r){
 84     if(L==l&&R==r)return sum[root];
 85     pushdown(root,l,r);
 86     int m=(l+r)>>1;
 87     if(R<=m)return query(lson[root],L,R,l,m);
 88     else if(L>m)return query(rson[root],L,R,m+1,r);
 89     else return query(lson[root],L,m,l,m)+query(rson[root],m+1,R,m+1,r);
 90 }
 91 int main(){
 92     int n,m,l,r,d,t;
 93     char op[5];
 94     while(~scanf("%d%d",&n,&m)){
 95         total = 0;
 96         int now = 0;
 97         Time[now]  = build(1,n);
 98         while(m--){
 99             scanf("%s",op);
100             if(op[0]=='C'){
101                 scanf("%d%d%d",&l,&r,&d);
102                 Time[now+1] = update(Time[now],l,r,d,1,n);
103                 ++now;
104             }else if(op[0]=='Q'){
105                 scanf("%d%d",&l,&r);
106                 cout<<query(Time[now],l,r,1,n)<<endl;
107             }else if(op[0]=='H'){
108                 scanf("%d%d%d",&l,&r,&t);
109                 cout<<query(Time[t],l,r,1,n)<<endl;
110             }else{
111                 scanf("%d",&t);
112                 now = t;
113             }
114         }
115         puts("");
116     }
117     return 0;
118 }

 

 

posted @ 2013-06-05 07:31  silver__bullet  阅读(495)  评论(0编辑  收藏  举报