1. 程式人生 > >51nod_1199 樹的先跟遍歷+區間更新樹狀數組

51nod_1199 樹的先跟遍歷+區間更新樹狀數組

turn sync main reel 進行 單個 sin www 操作

題目是中文,所以不講題意

做法順序如下:

  1. 使用先跟遍歷,把整棵樹平鋪到一維平面中
  2. 使用自己整的區間更新樹狀數組模板進行相關操作。
  3. http://www.cnblogs.com/rikka/p/7359185.html

放代碼如下:

  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 
  6 /*
  7 *常量MAXN用於設定樹狀數組的尺寸大小
  8 */
  9 const long long MAXN=500233;
 10 class TreeLikeArray
 11 {
 12     public:
13 /* 14 *數組c1用來儲存A[i]-A[i-1]; 15 */ 16 long long c1[MAXN]; 17 /* 18 *數組c2用來儲存(A[i]-A[i-1])*(i-1); 19 *或認為用於儲存(i-1)*c1[i]; 20 *兩種實現方式完全等價 21 */ 22 long long c2[MAXN]; 23 /* 24 *樹狀數組的常規操作,參數要求傳入數組並指明更新位置,以及更新參數。 25 *樹狀數組基礎底層操作 26 */ 27 void add(long long array[],long long
pos,long long key) 28 { 29 while(pos<MAXN) 30 { 31 array[pos]+=key; 32 pos+=pos&(-pos); 33 } 34 } 35 /* 36 *特別樹狀數組單點更新操作,要求傳入位置和參數 37 */ 38 void add(long long pos,long long key) 39 { 40 41 add(c1,pos,key);
42 add(c1,pos+1,-key); 43 add(c2,pos,(pos-1)*key); 44 add(c2,pos+1,-pos*key); 45 46 47 } 48 /* 49 *特別樹狀數組多點更新操作,要求傳入起始位置、終止位置和參數 50 *該操作將會使得[pos1,pos2]閉區間內所有元素得到更新 51 */ 52 void add(long long pos1,long long pos2,long long key) 53 { 54 add(c1,pos1,key); 55 add(c1,pos2+1,-key); 56 add(c2,pos1,(pos1-1)*key); 57 add(c2,pos2+1,-pos2*key); 58 } 59 /* 60 *樹狀數組的常規操作,參數要求傳入數組並指明求和位置 61 *樹狀數組基礎底層操作 62 */ 63 long long getSum(long long array[],long long pos) 64 { 65 long long ret=0; 66 while(pos>0) 67 { 68 ret+=array[pos]; 69 pos-=pos&(-pos); 70 }return ret; 71 } 72 /* 73 *從起始節點到目標節點閉區間求和[0,i] 74 */ 75 long long getSum(long long pos) 76 { 77 return pos*getSum(c1,pos)-getSum(c2,pos); 78 } 79 /* 80 *求[pos1,pos2]閉區間內元素和 81 */ 82 long long getSum(long long pos1,long long pos2) 83 { 84 return getSum(pos2)-getSum(pos1-1); 85 } 86 /* 87 *求pos單個元素的值 88 */ 89 long long getSingle(long long pos) 90 { 91 return getSum(pos,pos); 92 } 93 }; 94 TreeLikeArray TLA; 95 long long mapp[MAXN]; 96 long long son[MAXN]; 97 long long power[MAXN]; 98 vector<long long >G[MAXN]; 99 long long n,m; 100 101 long long point=1; 102 void dfs(long long x) 103 { 104 mapp[x]=point; 105 for(int i=0;i<G[x].size();++i) 106 { 107 point++; 108 dfs(G[x][i]); 109 } 110 son[x]=point; 111 } 112 113 void init() 114 { 115 cin>>n>>m; 116 for(int i=1;i<n;++i) 117 { 118 long long a,p; 119 cin>>a>>p; 120 G[a].push_back(i); 121 power[i]=p; 122 } 123 dfs(0); 124 for(int i=0;i<n;++i) 125 { 126 TLA.add(mapp[i],power[i]); 127 } 128 } 129 130 int main() 131 { 132 cin.sync_with_stdio(false); 133 134 init(); 135 for(int i=0;i<m;++i) 136 { 137 char c; 138 int a,b,z; 139 cin>>c>>a>>b>>z; 140 if(c==S) 141 { 142 long long x=TLA.getSingle(mapp[a]); 143 if(x<b)TLA.add(mapp[a],z); 144 }else 145 { 146 long long summ=TLA.getSum(mapp[a],son[a]); 147 if(summ<b*(son[a]-mapp[a]+1))TLA.add(mapp[a],son[a],z); 148 } 149 } 150 for(int i=0;i<n;++i) 151 { 152 cout<<TLA.getSingle(mapp[i])<<endl; 153 } 154 155 return 0; 156 }

51nod_1199 樹的先跟遍歷+區間更新樹狀數組