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 }
时间: 2024-10-10 00:06:50

hdu 4010 动态树 @的相关文章

hdu 5398 动态树LCT

GCD Tree Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 415    Accepted Submission(s): 172 Problem Description Teacher Mai has a graph with n vertices numbered from 1 to n. For every edge(u,v),

hdu 5002 (动态树lct)

Tree Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 920    Accepted Submission(s): 388 Problem Description You are given a tree with N nodes which are numbered by integers 1..N. Each node is a

hdu 5314 动态树

Happy King Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 821    Accepted Submission(s): 179 Problem Description There are n cities and n−1 roads in Byteland, and they form a tree. The citie

HDU 4010 Query on The Trees (动态树)(Link-Cut-Tree)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4010 题意; 先给你一棵树,有 \(4\) 种操作: 1.如果 \(x\) 和 \(y\) 不在同一棵树上则在\(x-y\)连边. 2.如果 \(x\) 和 \(y\) 在同一棵树上并且 \(x!=y\) 则把 \(x\) 换为树根并把 \(y\) 和 \(y\) 的父亲分离. 3.如果 \(x\) 和 \(y\) 在同一棵树上则 \(x\) 到 \(y\) 的路径上所有的点权值\(+w\). 4

hdu 4010 Query on The Trees(动态树)

题意:给定一幅图的连接情况,给出每个点的权值,四种操作: 1 x y 连接x.y所在子树: 2 x y 将同一棵树上的x,y分离,形成两棵子树: 3 w x y 将x.y之间路径上的所有点权加w: 4 x y 查询x.y路径上点权的最大值: 动态树学习参考:http://www.cnblogs.com/BLADEVIL/p/3510997.html http://wenku.baidu.com/view/75906f160b4e767f5acfcedb http://m.blog.csdn.ne

HDU 4836 The Query on the Tree lca || 欧拉序列 || 动态树

lca的做法还是很明显的,简单粗暴, 不过不是正解,如果树是长链就会跪,直接变成O(n).. 最后跑的也挺快,出题人还是挺阳光的.. 动态树的解法也是听别人说能ac的,估计就是放在splay上剖分一下,做法还是比较复杂的,,, 来一发lca: #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #inc

HDU 3966 Aragorn&#39;s Story 动态树

Aragorn's Story Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) [Problem Description] Our protagonist is the handsome human prince Aragorn comes from The Lord of the Rings. One day Aragorn finds a lot of enemies w

动态树LCT小结

最开始看动态树不知道找了多少资料,总感觉不能完全理解.但其实理解了就是那么一回事...动态树在某种意思上来说跟树链剖分很相似,都是为了解决序列问题,树链剖分由于树的形态是不变的,所以可以通过预处理节点间的关系,将树转化成连续的区间,再加以其它的数据结构,便能以较快的速度处理序列的修改和查询. 而动态树的问题,是包括了树的合并和拆分操作.这个时候,通过预处理实现的静态树的序列算法不能满足我们的要求,于是我们需要一颗‘动态’的树,能在O(logN)的时间复杂度,处理所有操作. Splay实现的Lin

动态树学习(留坑)

做了做鞍山网络赛的题,上来就不自量力的去做1006Tree http://acm.hdu.edu.cn/showproblem.php?pid=5002,特征非常明显的动态树.苦调2小时无果.其实还是熟练度不够,否则应该可以慢慢磨出来的.巨不爽,做的再多,比赛搞不出来,等于不会. 决定再学高级数据结构(主要动态树),不知道是第几次重新学了,QTREE系列和那几道历年省选题提交量都已刷屏. 学完,争取把http://www.lydsy.com/JudgeOnline/problem.php?id=