51nod_1199 树的先跟遍历+区间更新树状数组

Posted 六花的邪王真眼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod_1199 树的先跟遍历+区间更新树状数组相关的知识,希望对你有一定的参考价值。

题目是中文,所以不讲题意

做法顺序如下:

  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 树的先跟遍历+区间更新树状数组的主要内容,如果未能解决你的问题,请参考以下文章

51nod 第K大区间2(二分+树状数组)

51nod 平均数(二分+树状数组)

51nod 1832 先序遍历与后序遍历二叉树+高精度

51nod1199 Money out of Thin Air

ACM学习历程—51NOD 1685 第K大区间2(二分 && 树状数组 && 中位数)

51nod 1107(树状数组逆序数)