动态树(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; }
相关文章推荐
- Failed to convert value of type...no matching editors or conversion strategy found
- UIColectionView实现无限滚动(图片轮播)
- ios-UI控件精讲之【3】-UIWindow
- mybaties注解requestParam("id") String[] ids
- UIView基础笔记
- RabbitMQ Exchange & Queue Design Trade-off
- LeetCode-304. Range Sum Query 2D - Immutable
- [Locked] Verify Preorder Sequence in Binary Search Tree
- 使用phantomjs进行无界面UI自动化测试
- sequence有关问题
- hdu3530Subsequence【单调队列优化dp】2010多校联合
- 334. Increasing Triplet Subsequence【M】【69】
- STL_queue
- ios不同版本下的UILabel自动换行问题
- STL_deque
- 1101. Quick Sort (25)
- UITableViewControl的编辑(删除,添加,移动)
- IOS-53-图片、button等空间是否可拉伸设置;以及UITabelView的headerView设置
- 等待控件(UIActivityIndicatorView)不转动的原因
- Universal-Image-Loader(UIL)图片加载框架使用简单介绍