hdu 4348 To the moon
这题和这个是一样的,唯一的不同是内存限制变小了
今天学到了一种函数式线段树成段更新时节约内存的办法 。。。
先考虑朴素的仅支持成段加减的线段树,我们可以用方式解决:
1.正常的懒惰标记,当访问到带有懒惰标记节点的子区间时将标记下传;
2.不用下传的懒惰标记,我们用一个标记来记录当前节点的整段区间被累加了多少,当询问的时候我们在从根节点走到目标结点的过程中不断累加所经过节点上的标记值。。。
基于这两种思想,就有了函数式线段树的两种实现方式,第一种在pushdown的过程中会产生大量的结点,而第二种没有pushdown的过程,不会新建过多的节点
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 const int N = (int)3e6+10; 7 const int M = (int)1e5+10; 8 typedef long long ll; 9 int lson[N],rson[N],add[N]; 10 int Time[N]; 11 ll sum[N]; 12 int total; 13 void copy(int x,int y){ 14 lson[x] = lson[y]; 15 rson[x] = rson[y]; 16 add[x] = add[y]; 17 sum[x] = sum[y]; 18 } 19 inline void pushup(int root){ 20 sum[root] = sum[lson[root]] + sum[rson[root]]; 21 } 22 int build(int L,int R){ 23 int now = ++total; 24 add[now] = 0; 25 if(L==R){ 26 cin>>sum[now]; 27 lson[now] = rson[now] = 0; 28 return now; 29 } 30 int m=(L+R)>>1; 31 lson[now] = build(L,m); 32 rson[now] = build(m+1,R); 33 pushup(now); 34 return now; 35 } 36 int update(int root,int L,int R,int d,int l,int r){ 37 int now = ++total; 38 copy(now,root); 39 sum[now] += 1LL*d*(R-L+1); 40 if(L==l&&R==r){ 41 add[now] += d; 42 return now; 43 } 44 int m = (l+r)>>1; 45 if(R<=m) 46 lson[now] = update(lson[root],L,R,d,l,m); 47 else if(L>m) 48 rson[now] = update(rson[root],L,R,d,m+1,r); 49 else{ 50 lson[now] = update(lson[root],L,m,d,l,m); 51 rson[now] = update(rson[root],m+1,R,d,m+1,r); 52 } 53 return now; 54 } 55 ll query(int root,int L,int R,int l,int r){ 56 ll ans = 1LL*add[root]*(R-L+1); 57 if(L==l&&R==r)return sum[root]; 58 int m = (l+r)>>1; 59 if(R<=m) 60 ans+=query(lson[root],L,R,l,m); 61 else if(L>m) 62 ans+=query(rson[root],L,R,m+1,r); 63 else{ 64 ans+=query(lson[root],L,m,l,m); 65 ans+=query(rson[root],m+1,R,m+1,r); 66 } 67 return ans; 68 } 69 int main(){ 70 int n,m,l,r,d,t; 71 char op[5]; 72 while(cin>>n>>m){ 73 total = 0; 74 Time[0] = build(1,n); 75 int now = 0; 76 while(m--){ 77 scanf("%s",op); 78 if(op[0]=='Q'){ 79 scanf("%d%d",&l,&r); 80 cout<<query(Time[now],l,r,1,n)<<endl; 81 }else if(op[0]=='C'){ 82 scanf("%d%d%d",&l,&r,&d); 83 Time[now+1] = update(Time[now],l,r,d,1,n); 84 now++; 85 }else if(op[0]=='H'){ 86 scanf("%d%d%d",&l,&r,&t); 87 cout<<query(Time[t],l,r,1,n)<<endl; 88 }else{ 89 scanf("%d",&now); 90 } 91 } 92 } 93 return 0; 94 }