1. 程式人生 > >HDU - 4348 To the moon(主席樹區間更新)

HDU - 4348 To the moon(主席樹區間更新)

ring targe 鏈接 query panel iostream ref c++ span

題目鏈接:To the moon

題意:給個數組,三種操作,第一種詢問當前區間[l,r]的和,第二種給區間[l,r]的每一個數加上d,第三種詢問在第幾次修改後[l,r]的權值

題解:如果這題只詢問區間和更新,簡單建棵線段樹維護區間和用延時標記就可以了,但是它詢問第幾次修改之後一段區間的值,這樣的話剛才的方法就不好用,那我們可不可以,在每次修改之後的重新建一棵線段樹呢?直接重新建的話空間會爆,這個時候就可以用??幣的主席樹(沒學過主席樹可以先做一下這個),每次的修改只會再新增logN個節點,先把給的數組,建好第一棵主席樹(建的時候把add數組初始化為0),然後要然後之後的每次更新根據前面的主席樹,只要新增(log(n)個節點)。然後詢問的時候,用對應的主席樹詢問區間和就可以了。

  1 #include<bits/stdc++.h>
  2 #include<set>
  3 #include<cstdio>
  4 #include<iomanip>
  5 #include<iostream>
  6 #include<string>
  7 #include<cstring>
  8 #include<algorithm>
  9 #define pb push_back
 10 #define ll long long
 11 #define
PI 3.14159265 12 //#define ls l,m,rt<<1 13 //#define rs m+1,r,rt<<1|1 14 #define eps 1e-7 15 typedef unsigned long long ull; 16 const int mod=1e9+9; 17 const ll inf=0x3f3f3f3f3f3f3f; 18 const int maxn=1e5+5; 19 const int N=1e4+7; 20 using namespace std; 21 int n,m,ls[maxn*30
],rs[maxn*30],rt[maxn],t,tot; 22 ll sum[maxn*30],add[maxn*30]; 23 char op[5]; 24 void built(int &o,int l,int r) 25 { 26 o=++tot; 27 sum[o]=0;add[o]=0; 28 if(l==r) 29 { 30 scanf("%lld",&sum[o]);return ; 31 } 32 int m=(l+r)>>1; 33 built(ls[o],l,m); 34 built(rs[o],m+1,r); 35 sum[o]=sum[ls[o]]+sum[rs[o]]; 36 } 37 void up(int rt,int l,int r) 38 { 39 int m=(l+r)>>1; 40 sum[rt]=sum[ls[rt]]+sum[rs[rt]]+add[ls[rt]]*(m-l+1)+add[rs[rt]]*(r-m); 41 } 42 int update(int root,int l,int r,int L,int R,int val) 43 { 44 int newroot=++tot; 45 add[newroot]=add[root]; 46 if(L<=l&&r<=R) 47 { 48 ls[newroot]=ls[root]; 49 rs[newroot]=rs[root]; 50 sum[newroot]=sum[root]; 51 add[newroot]=add[root]+val; 52 return newroot; 53 } 54 int m=(l+r)>>1; 55 if(L<=m)ls[newroot]=update(ls[root],l,m,L,R,val); 56 else ls[newroot]=ls[root]; 57 if(R>m)rs[newroot]=update(rs[root],m+1,r,L,R,val); 58 else rs[newroot]=rs[root]; 59 up(newroot,l,r); 60 return newroot; 61 } 62 ll query(int rt,int l,int r,int L,int R,ll val) 63 { 64 if(L<=l&&r<=R) 65 { 66 return sum[rt]+1ll*(add[rt]+val)*(r-l+1); 67 } 68 int m=(l+r)>>1; 69 ll ans=0; 70 if(L<=m)ans+=query(ls[rt],l,m,L,R,val+add[rt]); 71 if(R>m)ans+=query(rs[rt],m+1,r,L,R,val+add[rt]); 72 return ans; 73 } 74 int main() 75 { 76 int l,r,val,T; 77 while(~scanf("%d %d",&n,&m)) 78 { 79 tot=0;t=0; 80 built(rt[0],1,n); 81 while(m--) 82 { 83 scanf("%s",op); 84 if(op[0]==Q) 85 { 86 scanf("%d %d",&l,&r); 87 printf("%lld\n",query(rt[t],1,n,l,r,0)); 88 } 89 else if(op[0]==C) 90 { 91 92 scanf("%d %d %d",&l,&r,&val); 93 rt[t+1]=update(rt[t],1,n,l,r,val); 94 t++; 95 } 96 else if(op[0]==H) 97 { 98 scanf("%d %d %d",&l,&r,&T); 99 printf("%lld\n",query(rt[T],1,n,l,r,0)); 100 } 101 else 102 { 103 scanf("%d",&T); 104 tot=rt[T+1]; 105 t=T; 106 } 107 } 108 } 109 return 0; 110 }

HDU - 4348 To the moon(主席樹區間更新)