您的位置:首页 > 产品设计 > UI/UE

动态树(LCT):HDU 4010 Query on The Trees

2016-02-23 22:55 537 查看

Query on The Trees

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


[align=left]Problem Description[/align]
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!

[align=left]Input[/align]
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.

[align=left]Output[/align]
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.

[align=left]Sample Input[/align]

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

[align=left]Sample Output[/align]
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.

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;
const int MAXN=300010;
int fir[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt;
int Max[MAXN],fa[MAXN],ch[MAXN][2],flip[MAXN],add[MAXN],key[MAXN];
bool rt[MAXN];

void Push_up(int p)
{
Max[p]=max(key[p],max(Max[ch[p][0]],Max[ch[p][1]]));
}

void Add(int p,int d)
{
if(!p)return;
key[p]+=d;
Max[p]+=d;
add[p]+=d;
}
void Flip(int p)
{
if(!p)return;
swap(ch[p][0],ch[p][1]);
flip[p]^=1;
}
void Push_down(int p)
{
if(add[p]){
Add(ch[p][0],add[p]);
Add(ch[p][1],add[p]);
add[p]=0;
}
if(flip[p]){
Flip(ch[p][0]);
Flip(ch[p][1]);
flip[p]=0;
}
}

void Rotate(int x)
{
int y=fa[x],g=fa[y],c=ch[y][1]==x;
ch[y][c]=ch[x][c^1];fa[ch[y][c]]=y;
ch[x][c^1]=y;fa[y]=x;fa[x]=g;
if(rt[y])
rt[y]=false,rt[x]=true;
else
ch[g][ch[g][1]==y]=x;
Push_up(y);
}

void P(int p)
{
if(!rt[p])P(fa[p]);
Push_down(p);
}

void Splay(int x)
{
P(x);
for(int y=fa[x];!rt[x];Rotate(x),y=fa[x])
if(!rt[y])
Rotate((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x);
Push_up(x);
}

bool Judge(int x,int y)
{
while(fa[x])x=fa[x];
while(fa[y])y=fa[y];
return x==y;
}

void Access(int x)
{
int y=0;
while(x)
{
Splay(x);
rt[ch[x][1]]=true;
rt[ch[x][1]=y]=false;
Push_up(x);
x=fa[y=x];
}
}
void Lca(int &x,int &y)
{
Access(y);y=0;
while(true)
{
Splay(x);
if(!fa[x])return;
rt[ch[x][1]]=true;
rt[ch[x][1]=y]=false;
Push_up(x);
x=fa[y=x];
}
}
void Make_root(int x)
{
Access(x);
Splay(x);
Flip(x);
}

void Link(int x,int y)
{
if(Judge(x,y)){
printf("-1\n");
return;
}
Make_root(x);
Splay(x);
fa[x]=y;
}

void Cut(int x,int y)
{
if(x==y||!Judge(x,y)){
printf("-1\n");
return;
}
Make_root(x);
Splay(y);
fa[ch[y][0]]=fa[y];
fa[y]=0;
rt[ch[y][0]]=true;
ch[y][0]=0;
Push_up(y);
}

void Change(int x,int y,int d)
{
if(!Judge(x,y)){
printf("-1\n");
return;
}
Lca(x,y);
Add(ch[x][1],d);
Add(y,d);
key[x]+=d;
Push_up(x);
}

void Query(int x,int y)
{
if(!Judge(x,y)){
printf("-1\n");
return;
}
Lca(x,y);
printf("%d\n",max(key[x],max(Max[ch[x][1]],Max[y])));
}

void addedge(int a,int b)
{
nxt[++cnt]=fir[a];to[cnt]=b;fir[a]=cnt;
}

void DFS(int node,int pre)
{
for(int i=fir[node];i;i=nxt[i])
if(to[i]!=pre){
fa[to[i]]=node;
DFS(to[i],node);
}
}
void Init()
{
memset(fir,0,sizeof(fir));
memset(ch,0,sizeof(ch));
memset(fa,0,sizeof(fa));
memset(rt,-1,sizeof(rt));
memset(flip,0,sizeof(flip));
memset(add,0,sizeof(add));
cnt=0;Max[0]=-2100000000;
}
int main()
{
int Q,n,x,y,d,k;
while(~scanf("%d",&n))
{
Init();
for(int i=1;i<n;i++){
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
for(int i=1;i<=n;i++){
scanf("%d",&key[i]);
Max[i]=key[i];
}
DFS(1,1);
scanf("%d",&Q);
while(Q--)
{
scanf("%d",&k);
if(k==1){
scanf("%d%d",&x,&y);
Link(x,y);
}
else if(k==2){
scanf("%d%d",&x,&y);
Cut(x,y);
}
else if(k==3){
scanf("%d%d%d",&d,&x,&y);
Change(x,y,d);
}
else if(k==4){
scanf("%d%d",&x,&y);
Query(x,y);
}
}
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: