hdu 4010 动态树 @

kuangbin模板题,看起来十分高大上

  1 /* ***********************************************
  2 Author        :kuangbin
  3 Created Time  :2013-9-4 0:13:15
  4 File Name     :HDU4010.cpp
  5 ************************************************ */
  6 
  7 #include <stdio.h>
  8 #include <string.h>
  9 #include <iostream>
 10 #include <algorithm>
 11 #include <vector>
 12 #include <queue>
 13 #include <set>
 14 #include <map>
 15 #include <string>
 16 #include <math.h>
 17 #include <stdlib.h>
 18 #include <time.h>
 19 using namespace std;
 20 //动态维护一组森林,要求支持一下操作:
 21 //link(a,b) : 如果a,b不在同一颗子树中,则通过在a,b之间连边的方式,连接这两颗子树
 22 //cut(a,b)  : 如果a,b在同一颗子树中,且a!=b,则将a视为这颗子树的根以后,切断b与其父亲结点的连接
 23 //ADD(a,b,w): 如果a,b在同一颗子树中,则将a,b之间路径上所有点的点权增加w
 24 //query(a,b): 如果a,b在同一颗子树中,返回a,b之间路径上点权的最大值
 25 const int MAXN = 300010;
 26 int ch[MAXN][2],pre[MAXN],key[MAXN];
 27 int add[MAXN],rev[MAXN],Max[MAXN];
 28 bool rt[MAXN];
 29 
 30 void Update_Add(int r,int d)
 31 {
 32     if(!r)return;
 33     key[r] += d;
 34     add[r] += d;
 35     Max[r] += d;
 36 }
 37 void Update_Rev(int r)
 38 {
 39     if(!r)return;
 40     swap(ch[r][0],ch[r][1]);
 41     rev[r] ^= 1;
 42 }
 43 void push_down(int r)
 44 {
 45     if(add[r])
 46     {
 47         Update_Add(ch[r][0],add[r]);
 48         Update_Add(ch[r][1],add[r]);
 49         add[r] = 0;
 50     }
 51     if(rev[r])
 52     {
 53         Update_Rev(ch[r][0]);
 54         Update_Rev(ch[r][1]);
 55         rev[r] = 0;
 56     }
 57 }
 58 void push_up(int r)
 59 {
 60     Max[r] = max(max(Max[ch[r][0]],Max[ch[r][1]]),key[r]);
 61 }
 62 void Rotate(int x)
 63 {
 64     int y = pre[x], kind = ch[y][1]==x;
 65     ch[y][kind] = ch[x][!kind];
 66     pre[ch[y][kind]] = y;
 67     pre[x] = pre[y];
 68     pre[y] = x;
 69     ch[x][!kind] = y;
 70     if(rt[y])
 71         rt[y] = false, rt[x] = true;
 72     else
 73         ch[pre[x]][ch[pre[x]][1]==y] = x;
 74     push_up(y);
 75 }
 76 //P函数先将根结点到r的路径上所有的结点的标记逐级下放
 77 void P(int r)
 78 {
 79     if(!rt[r])P(pre[r]);
 80     push_down(r);
 81 }
 82 void Splay(int r)
 83 {
 84     P(r);
 85     while( !rt[r] )
 86     {
 87         int f = pre[r], ff = pre[f];
 88         if(rt[f])
 89             Rotate(r);
 90         else if( (ch[ff][1]==f)==(ch[f][1]==r) )
 91             Rotate(f), Rotate(r);
 92         else
 93             Rotate(r), Rotate(r);
 94     }
 95     push_up(r);
 96 }
 97 int Access(int x)
 98 {
 99     int y = 0;
100     for( ; x ; x = pre[y=x])
101     {
102         Splay(x);
103         rt[ch[x][1]] = true, rt[ch[x][1]=y] = false;
104         push_up(x);
105     }
106     return y;
107 }
108 //判断是否是同根(真实的树,非splay)
109 bool judge(int u,int v)
110 {
111     while(pre[u]) u = pre[u];
112     while(pre[v]) v = pre[v];
113     return u == v;
114 }
115 //使r成为它所在的树的根
116 void mroot(int r)
117 {
118     Access(r);
119     Splay(r);
120     Update_Rev(r);
121 }
122 //调用后u是原来u和v的lca,v和ch[u][1]分别存着lca的2个儿子
123 //(原来u和v所在的2颗子树)
124 void lca(int &u,int &v)
125 {
126     Access(v), v = 0;
127     while(u)
128     {
129         Splay(u);
130         if(!pre[u])return;
131         rt[ch[u][1]] = true;
132         rt[ch[u][1]=v] = false;
133         push_up(u);
134         u = pre[v = u];
135     }
136 }
137 void link(int u,int v)
138 {
139     if(judge(u,v))
140     {
141         puts("-1");
142         return;
143     }
144     mroot(u);
145     pre[u] = v;
146 }
147 //使u成为u所在树的根,并且v和它父亲的边断开 
148 void cut(int u,int v)
149 {
150     if(u == v || !judge(u,v))
151     {
152         puts("-1");
153         return;
154     }
155     mroot(u);
156     Splay(v);
157     pre[ch[v][0]] = pre[v];
158     pre[v] = 0;
159     rt[ch[v][0]] = true;
160     ch[v][0] = 0;
161     push_up(v);
162 }
163 void ADD(int u,int v,int w)
164 {
165     if(!judge(u,v))
166     {
167         puts("-1");
168         return;
169     }
170     lca(u,v);
171     Update_Add(ch[u][1],w);
172     Update_Add(v,w);
173     key[u] += w;
174     push_up(u);
175 }
176 void query(int u,int v)
177 {
178     if(!judge(u,v))
179     {
180         puts("-1");
181         return;
182     }
183     lca(u,v);
184     printf("%d\n",max(max(Max[v],Max[ch[u][1]]),key[u]));
185 }
186 
187 struct Edge
188 {
189     int to,next;
190 }edge[MAXN*2];
191 int head[MAXN],tot;
192 void addedge(int u,int v)
193 {
194     edge[tot].to = v;
195     edge[tot].next = head[u];
196     head[u] = tot++;
197 }
198 void dfs(int u)
199 {
200     for(int i = head[u];i != -1; i = edge[i].next)
201     {
202         int v = edge[i].to;
203         if(pre[v] != 0)continue;
204         pre[v] = u;
205         dfs(v);
206     }
207 }
208 
209 int main()
210 {
211     //freopen("in.txt","r",stdin);
212     //freopen("out.txt","w",stdout);
213     int n,q,u,v;
214     while(scanf("%d",&n) == 1)
215     {
216         tot = 0;
217         for(int i = 0;i <= n;i++)
218         {
219             head[i] = -1;
220             pre[i] = 0;
221             ch[i][0] = ch[i][1] = 0;
222             rev[i] = 0;
223             add[i] = 0;
224             rt[i] = true;
225         }
226         Max[0] = -2000000000;
227         for(int i = 1;i < n;i++)
228         {
229             scanf("%d%d",&u,&v);
230             addedge(u,v);
231             addedge(v,u);
232         }
233         for(int i = 1;i <= n;i++)
234         {
235             scanf("%d",&key[i]);
236             Max[i] = key[i];
237         }
238         scanf("%d",&q);
239         pre[1] = -1;
240         dfs(1);
241         pre[1] = 0;
242         int op;
243         while(q--)
244         {
245             scanf("%d",&op);
246             if(op == 1)
247             {
248                 int x,y;
249                 scanf("%d%d",&x,&y);
250                 link(x,y);
251             }
252             else if(op == 2)
253             {
254                 int x,y;
255                 scanf("%d%d",&x,&y);
256                 cut(x,y);
257             }
258             else if(op == 3)
259             {
260                 int w,x,y;
261                 scanf("%d%d%d",&w,&x,&y);
262                 ADD(x,y,w);
263             }
264             else
265             {
266                 int x,y;
267                 scanf("%d%d",&x,&y);
268                 query(x,y);
269             }
270         }
271         printf("\n");
272     }
273     return 0;
274 }

 

posted @ 2015-07-29 22:37  miao_a_miao  阅读(178)  评论(2编辑  收藏  举报