HDU 4010 Query on The Trees(动态树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4010

题意:一棵树,四种操作:

(1)若x和y不在一棵树上,将x和y连边;

(2)若x和y在一棵树上,将x变成树根,将y从x树上分离;

(3)若x和y在一棵树上,将x到y路径上的所有值增加det;

(4)若x和y在一棵树上,输出x到y路径上的最大值。

思路:1操作用link维护,2操作用cut,34操作先split(x,y),然后对y做tag,并且记录路径的max值。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<string>
  6 #include<algorithm>
  7 int tot,go[600005],next[600005],first[300005];
  8 int ch[600005][2],rev[600005],tag[600005],q[600005];
  9 int st[600005],mx[600005],fa[600005],v[600005];
 10 bool pd(int x){
 11     return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
 12 }
 13 void insert(int x,int y){
 14     tot++;go[tot]=y;next[tot]=first[x];first[x]=tot;
 15 }
 16 void addedge(int x,int y){
 17     insert(x,y);insert(y,x);
 18 }
 19 void pushdown(int x){
 20     int l=ch[x][0],r=ch[x][1];
 21     if (rev[x]){
 22         rev[x]^=1;rev[l]^=1;rev[r]^=1;
 23         std::swap(ch[x][0],ch[x][1]);
 24     }
 25     if (tag[x]){
 26         if (l) tag[l]+=tag[x],v[l]+=tag[x],mx[l]+=tag[x];
 27         if (r) tag[r]+=tag[x],mx[r]+=tag[x],v[r]+=tag[x];
 28         tag[x]=0;
 29     }
 30 }
 31 void updata(int x){
 32     int l=ch[x][0],r=ch[x][1];
 33     mx[x]=std::max(v[x],std::max(mx[l],mx[r]));
 34 }
 35 void rotate(int x){
 36     int y=fa[x],z=fa[y],l,r;
 37     if (ch[y][0]==x) l=0;else l=1;r=l^1;
 38     if (!pd(y)){
 39         if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;
 40     }
 41     fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
 42     ch[y][l]=ch[x][r];ch[x][r]=y;
 43     updata(y);updata(x);
 44 }
 45 void splay(int x){
 46     int top=0;st[++top]=x;
 47     for (int i=x;!pd(i);i=fa[i])
 48      st[++top]=fa[i];
 49     for (int i=top;i;i--)
 50      pushdown(st[i]);
 51     while (!pd(x)){
 52         int y=fa[x],z=fa[y];
 53         if (!pd(y)){
 54             if (ch[y][0]==x^ch[z][0]==y) rotate(x);
 55             else rotate(y);
 56         }
 57         rotate(x);
 58     }
 59 }
 60 void access(int x){
 61     for (int t=0;x;t=x,x=fa[x]){
 62         splay(x);
 63         ch[x][1]=t;
 64         updata(x);
 65     }
 66 }
 67 void makeroot(int x){
 68     access(x);splay(x);rev[x]^=1;
 69 }
 70 void cut(int x,int y){
 71     makeroot(x);access(y);splay(y);ch[y][0]=fa[ch[y][0]]=0;updata(y);
 72 }
 73 void link(int x,int y){
 74     makeroot(x);
 75     fa[x]=y;
 76 }
 77 int find(int x){
 78     access(x);splay(x);
 79     while (ch[x][0]) x=ch[x][0];
 80     return x;
 81 }
 82 void add(int x,int y,int val){
 83     makeroot(x);access(y);splay(y);
 84     mx[y]+=val;v[y]+=val;tag[y]+=val;
 85 }
 86 int main(){
 87     int n,x,y,m,opt,w;
 88     while (scanf("%d",&n)!=EOF){
 89         mx[0]=-2000000000;
 90         for (int i=0;i<=n;i++)
 91          mx[i]=tag[i]=rev[i]=v[i]=ch[i][0]=ch[i][1]=fa[i]=0;
 92         memset(first,0,sizeof first);tot=0;
 93         for (int i=1;i<n;i++){
 94          scanf("%d%d",&x,&y);
 95          addedge(x,y);
 96         }
 97         for (int i=1;i<=n;i++){
 98             scanf("%d",&v[i]);
 99             mx[i]=v[i];
100         }
101         int top=1;
102         q[top]=1;
103         for (int k=1;k<=top;k++){
104             for (int i=first[q[k]];i;i=next[i]){
105                 int pur=go[i];
106                 if (pur==fa[q[k]]) continue;
107                 fa[pur]=q[k];
108                 q[++top]=pur;
109             }
110         }
111         top=0;
112         scanf("%d",&m);
113         while (m--){
114             scanf("%d",&opt);
115             if (opt==1){
116                 scanf("%d%d",&x,&y);
117                 if (find(x)==find(y)) {puts("-1");continue;}
118                 link(x,y);
119             }
120             else
121             if (opt==2){
122                 scanf("%d%d",&x,&y);
123                 if (find(x)!=find(y)||x==y) {puts("-1");continue;}
124                 cut(x,y);
125             }
126             else
127             if (opt==3){
128                 scanf("%d%d%d",&w,&x,&y);
129                 if (find(x)!=find(y)){puts("-1");continue;}
130                 add(x,y,w);
131             }
132             else
133             if (opt==4)
134             {
135                 scanf("%d%d",&x,&y);
136                 if (find(x)!=find(y)){
137                     printf("-1\n");
138                     continue;
139                 }
140                 makeroot(x);access(y);splay(y);
141                 printf("%d\n",mx[y]);
142             }
143         }
144         printf("\n");
145     }
146 }
时间: 2024-12-09 11:40:54

HDU 4010 Query on The Trees(动态树)的相关文章

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 4010.Query on The Trees 解题报告

题意: 给出一颗树,有4种操作: 1.如果x和y不在同一棵树上则在xy连边 2.如果x和y在同一棵树上并且x!=y则把x换为树根并把y和y的父亲分离 3.如果x和y在同一棵树上则x到y的路径上所有的点权值+w 4.如果x和y在同一棵树上则输出x到y路径上的最大值 动态树入门题: #include <iostream> #include <cstdio> using namespace std; const int MAXN = 333333; struct node { int v

HDU 4010 Query on The Trees

题意: 一棵树  支持合并.分离.路径加权值.路径权值最大值 思路: LCT入门题  也是我的第一道-  代码来源于kuangbin巨巨  我只是整理出自己的风格留作模版- LCT比较好的入门资料是--<QTREE解法的一些研究> LCT基本做法就是先dfs建树  然后根据输入做上述4个操作 对于合并  就是把u转到树根  然后接在v上 对于分离  就是把u转到splay的根  然后切断与左子树的连接 对于路径加值  就是求出lca  然后包含u和v的子树以及lca点进行加值 对于路径求最值 

hdu 4010 Query on the trees LCT

维护一个带点权的无向图森林,支持: 1.删边 2.加边 3.增加某条链所有点的点权 4.求某条链上点权的最大值 大概思路: 前两个需要更改根(即需要翻转标记) 第三个又需要一个标记,第四个每个节点记录该splay中以该节点为根的子树的最大点权. 收获: 1.对于splay前的标记下传可用递归写法, 虽然慢一点,但不容易写错. 2.access的过程中,在边转换完成后要更新节点信息. 3.对于寻找某子树的根,可以一直向上(会途径重边和轻边)找,这样比access+splay快很多,也很好写. 4.

HDOJ 4010 Query on The Trees LCT

LCT: 分割.合并子树,路径上全部点的点权添加一个值,查询路径上点权的最大值 Query on The Trees Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Submission(s): 2582    Accepted Submission(s): 1208 Problem Description We have met so many problems

HDOJ 题目4010 Query on The Trees(Link Cut Tree连接,删边,路径点权加,路径点权最大值)

Query on The Trees Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Submission(s): 3602    Accepted Submission(s): 1587 Problem Description We have met so many problems on the tree, so today we will have a qu

HDU 3804 Query on a tree (树链剖分)

题目链接~~> 做题感悟:这题开始想错的方法,开始想用二分来着,但是写出来之后发现不对,悲剧.. 解题思路: 看到这种只有询问没有修改的就有点离线的感脚.果不其然,就是用离线,因为要查询路径上不大于 Wi 的最大权值 ,so 我们可以以 Wi 为标准往线段树中插入数据,然后就是问线,跟求逆序数差不多.这样就不会影响最终结果,处理完后排个序就ok 了. 代码: #pragma comment(linker, "/STACK:1024000000,1024000000") #incl

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