51nod_1199 树的先跟遍历+区间更新树状数组
Posted 六花的邪王真眼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod_1199 树的先跟遍历+区间更新树状数组相关的知识,希望对你有一定的参考价值。
题目是中文,所以不讲题意
做法顺序如下:
- 使用先跟遍历,把整棵树平铺到一维平面中
- 使用自己整的区间更新树状数组模板进行相关操作。
- 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 树的先跟遍历+区间更新树状数组的主要内容,如果未能解决你的问题,请参考以下文章
51nod1199 Money out of Thin Air