Hdu 4010-Query on The Trees LCT,动态树

Query on The Trees

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 4091    Accepted Submission(s): 1774

Problem Description

We have met so many problems on the tree, so today we will have a query problem on a set of trees. 
There are N nodes, each node will have a unique weight Wi. We will have four kinds of operations on it and you should solve them efficiently. Wish you have fun!

Input

There are multiple test cases in our dataset. 
For each case, the first line contains only one integer N.(1 ≤ N ≤ 300000) The next N‐1 lines each contains two integers x, y which means there is an edge between them. It also means we will give you one tree initially. 
The next line will contains N integers which means the weight Wi of each node. (0 ≤ Wi ≤ 3000) 
The next line will contains an integer Q. (1 ≤ Q ≤ 300000) The next Q lines will start with an integer 1, 2, 3 or 4 means the kind of this operation. 
1. Given two integer x, y, you should make a new edge between these two node x and y. So after this operation, two trees will be connected to a new one. 
2. Given two integer x, y, you should find the tree in the tree set who contain node x, and you should make the node x be the root of this tree, and then you should cut the edge between node y and its parent. So after this operation, a tree will be separate into two parts. 
3. Given three integer w, x, y, for the x, y and all nodes between the path from x to y, you should increase their weight by w. 
4. Given two integer x, y, you should check the node weights on the path between x and y, and you should output the maximum weight on it.

Output

For each query you should output the correct answer of it. If you find this query is an illegal operation, you should output ‐1. 
You should output a blank line after each test case.

Sample Input

5
1 2
2 4
2 5
1 3
1 2 3 4 5
6
4 2 3
2 1 2
4 2 3
1 3 5
3 2 1 4
4 1 4

Sample Output

3
-1
7

Hint

We define the illegal situation of different operations:
In first operation: if node x and y belong to a same tree, we think it‘s illegal.
In second operation: if x = y or x and y not belong to a same tree, we think it‘s illegal.
In third operation: if x and y not belong to a same tree, we think it‘s illegal.
In fourth operation: if x and y not belong to a same tree, we think it‘s illegal.

Source

The 36th ACM/ICPC Asia Regional Dalian Site —— Online Contest

Recommend

lcy

题解:

LCT的子树问题。

找到每个点所在的原始树(不是Splay树)的根。

又是子树判断最麻烦。。。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define MAXN 300010
  4 #define INF 1e9
  5 struct node
  6 {
  7     int left,right,val,mx;
  8 }tree[MAXN];
  9 struct NODE
 10 {
 11     int begin,end,next;
 12 }edge[MAXN*2];
 13 int father[MAXN],rev[MAXN],tag[MAXN],U[MAXN],V[MAXN],Stack[MAXN],Head[MAXN],cnt;
 14 void addedge(int bb,int ee)
 15 {
 16     edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].next=Head[bb];Head[bb]=cnt;
 17 }
 18 void addedge1(int bb,int ee)
 19 {
 20     addedge(bb,ee);addedge(ee,bb);
 21 }
 22 int read()
 23 {
 24     int s=0,fh=1;char ch=getchar();
 25     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)fh=-1;ch=getchar();}
 26     while(ch>=‘0‘&&ch<=‘9‘){s=s*10+(ch-‘0‘);ch=getchar();}
 27     return s*fh;
 28 }
 29 int isroot(int x)
 30 {
 31     return tree[father[x]].left!=x&&tree[father[x]].right!=x;
 32 }
 33 void pushdown(int x)
 34 {
 35     int l=tree[x].left,r=tree[x].right;
 36     if(rev[x]!=0)
 37     {
 38         rev[x]^=1;rev[l]^=1;rev[r]^=1;
 39         swap(tree[x].left,tree[x].right);
 40     }
 41     if(tag[x]!=0)
 42     {
 43         /*tag[l]+=tag[x];tag[r]+=tag[x];
 44         tree[l].val+=tag[x];tree[r].val+=tag[x];
 45         tree[l].mx+=tag[x];tree[r].mx+=tag[x];*/
 46         if(l!=0){tag[l]+=tag[x];tree[l].val+=tag[x];tree[l].mx+=tag[x];}
 47         if(r!=0){tag[r]+=tag[x];tree[r].val+=tag[x];tree[r].mx+=tag[x];}
 48         tag[x]=0;
 49     }
 50 }
 51 void Pushup(int x)
 52 {
 53     int l=tree[x].left,r=tree[x].right;
 54     tree[x].mx=max(max(tree[l].mx,tree[r].mx),tree[x].val);
 55 }
 56 void rotate(int x)
 57 {
 58     int y=father[x],z=father[y];
 59     if(!isroot(y))
 60     {
 61         if(tree[z].left==y)tree[z].left=x;
 62         else tree[z].right=x;
 63     }
 64     if(tree[y].left==x)
 65     {
 66         father[x]=z;father[y]=x;tree[y].left=tree[x].right;tree[x].right=y;father[tree[y].left]=y;
 67     }
 68     else
 69     {
 70         father[x]=z;father[y]=x;tree[y].right=tree[x].left;tree[x].left=y;father[tree[y].right]=y;
 71     }
 72     Pushup(y);Pushup(x);
 73 }
 74 void splay(int x)
 75 {
 76     int top=0,i,y,z;Stack[++top]=x;
 77     for(i=x;!isroot(i);i=father[i])Stack[++top]=father[i];
 78     for(i=top;i>=1;i--)pushdown(Stack[i]);
 79     while(!isroot(x))
 80     {
 81         y=father[x];z=father[y];
 82         if(!isroot(y))
 83         {
 84             if((tree[y].left==x)^(tree[z].left==y))rotate(x);
 85             else rotate(y);
 86         }
 87         rotate(x);
 88     }
 89 }
 90 void access(int x)
 91 {
 92     int last=0;
 93     while(x!=0)
 94     {
 95         splay(x);
 96         tree[x].right=last;Pushup(x);
 97         last=x;x=father[x];
 98     }
 99 }
100 void makeroot(int x)
101 {
102     access(x);splay(x);rev[x]^=1;
103 }
104 void link(int u,int v)
105 {
106     /*access(u);*/makeroot(u);father[u]=v;//splay(u);
107 }
108 void cut(int u,int v)
109 {
110     /*access(u);*/makeroot(u);access(v);splay(v);/*father[u]=tree[v].left=0;*/father[tree[v].left]=0;tree[v].left=0;Pushup(v);
111 }
112 int findroot(int x)
113 {
114     access(x);splay(x);
115     while(tree[x].left!=0)x=tree[x].left;
116     return x;
117 }
118 int main()
119 {
120     int n,i,w,x,y,fh,Q,top=0,u,j,v;
121     while(scanf("%d",&n)!=EOF)
122     {
123         top=0;
124         for(i=0;i<=n;i++)tree[i].val=tree[i].mx=tree[i].left=tree[i].right=rev[i]=tag[i]=father[i]=0;
125         tree[0].mx=-INF;
126         memset(Head,-1,sizeof(Head));cnt=1;
127         for(i=1;i<n;i++)
128         {
129             U[i]=read();V[i]=read();
130             addedge1(U[i],V[i]);
131         }
132         Stack[++top]=1;
133         for(i=1;i<=top;i++)
134         {
135             u=Stack[i];
136             for(j=Head[u];j!=-1;j=edge[j].next)
137             {
138                 v=edge[j].end;
139                 if(v!=father[u])
140                 {
141                     father[v]=u;
142                     Stack[++top]=v;
143                 }
144             }
145         }
146         for(i=1;i<=n;i++)tree[i].mx=tree[i].val=read();
147         //for(i=1;i<n;i++)link(U[i],V[i]);
148         Q=read();
149         for(i=1;i<=Q;i++)
150         {
151             fh=read();
152             if(fh==1)
153             {
154                 x=read();y=read();
155                 if(findroot(x)!=findroot(y))link(x,y);
156                 else {printf("-1\n");continue;}
157             }
158             else if(fh==2)
159             {
160                 x=read();y=read();
161                 if(findroot(x)==findroot(y)&&x!=y)
162                 {
163                     /*makeroot(x);*/cut(x,y);
164                     //access(y);access(father[y]);splay(father[y]);father[y]=tree[father[y]].left=0;
165                 }
166                 else {printf("-1\n");continue;}
167             }
168             else if(fh==3)
169             {
170                 w=read();x=read();y=read();
171                 if(findroot(x)==findroot(y))
172                 {
173                     makeroot(x);access(y);splay(y);
174                     tag[y]+=w;tree[y].mx+=w;tree[y].val+=w;
175                 }
176                 else {printf("-1\n");continue;}
177             }
178             else
179             {
180                 x=read();y=read();
181                 makeroot(x);access(y);splay(y);
182                 if(findroot(x)!=findroot(y)){printf("-1\n");continue;}
183                 printf("%d\n",tree[y].mx);
184             }
185         }
186         printf("\n");
187     }
188     return 0;
189 }

时间: 2024-10-12 16:04:38

Hdu 4010-Query on The Trees LCT,动态树的相关文章

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 LCT

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

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

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

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(动态树)

题目链接: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<iost

HDU 4010 Query on The Trees

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

HDU4010 Query on The Trees(LCT)

人生的第一道动态树,为了弄懂它的大致原理,需要具备一些前置技能,如Splay树,树链剖分的一些概念.在这里写下一些看各种论文时候的心得,下面的代码是拷贝的CLJ的模板,别人写的模板比较可靠也方便自己学习理解,然后一些概念的则是学习了一些论文,下面的内容可以看作对别人模板的理解心得,以及对论文的收获体会. LCT支持的主要是一种树路径上的操作,譬如说对u和v之间的路径上询问点权的和,询问点权的最大值,对所有点权加一个数,置为一个树等等.它和树链剖分不同的是,它支持将这个树上的边切掉,也支持将两个树

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