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 }