HDOJ 题目4010 Query on The Trees(Link Cut Tree连接,删边,路径点权加,路径点权最大值)
2015-08-28 01:48
931 查看
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
[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.
[align=left]Source[/align]
The 36th ACM/ICPC Asia Regional Dalian
Site —— Online Contest
[align=left]Recommend[/align]
lcy | We have carefully selected several similar problems for you: 4004 4005 4007 4001 4008
题目大意:n个点,n-1条边,每个点都有一个点权,操作1 连接 x y,操作2断开x y,操作3 (先输入的val)x到y的路径上的点权都加val,操作4,求x到y的路径上的最大点权值
ac代码
确实kuangbin的代码要快些,跑了800多,但是我就是看不太习惯,,还是用自己习惯的写法吧。。。
#include<stdio.h> #include<string.h> #include<queue> #include<iostream> #define INF 0x7fffffff #define N 300030 #define max(a,b) (a>b?a:b) using namespace std; int vis ; struct LCT { int bef ,pre ,next [2],key ,add ; int rev ,maxn ; void init() { memset(pre,0,sizeof(pre)); memset(next,0,sizeof(next)); rev[0]=rev[1]=0; add[0]=add[1]=0; bef[0]=bef[1]=0; maxn[0]=key[0]=0; } void update_add(int x,int val) { if(x) { add[x]+=val; key[x]+=val; maxn[x]+=val; } } void update_rev(int x) { if(!x) return; swap(next[x][0],next[x][1]); rev[x]^=1; } void pushup(int x) { maxn[x] = max(key[x], max(maxn[next[x][0]], maxn[next[x][1]])); } void pushdown(int x) { if(add[x]) { update_add(next[x][0],add[x]); update_add(next[x][1],add[x]); add[x]=0; } if(rev[x]) { update_rev(next[x][0]); update_rev(next[x][1]); // swap(next[x][0],next[x][1]); rev[x]=0; } } void rotate(int x,int kind) { int y,z; y=pre[x]; z=pre[y]; pushdown(y); pushdown(x); next[y][!kind]=next[x][kind]; pre[next[x][kind]]=y; next[z][next[z][1]==y]=x; pre[x]=z; next[x][kind]=y; pre[y]=x; pushup(y); } void splay(int x) { int rt; for(rt=x;pre[rt];rt=pre[rt]); if(x!=rt) { bef[x]=bef[rt]; bef[rt]=0; pushdown(x); while(pre[x]) { if(next[pre[x]][0]==x) { rotate(x,1); } else rotate(x,0); } pushup(x); } } void access(int x) { int fa; for(fa=0;x;x=bef[x]) { splay(x); pushdown(x); pre[next[x][1]]=0; bef[next[x][1]]=x; next[x][1]=fa; pre[fa]=x; bef[fa]=0; fa=x; pushup(x); } } int getroot(int x) { access(x); splay(x); while(next[x][0]) x=next[x][0]; return x; } void makeroot(int x) { access(x); splay(x); update_rev(x); } void link(int x,int y) { makeroot(x); makeroot(y); bef[x]=y; } void cut(int y,int x) { makeroot(y); access(x); splay(x); bef[next[x][0]]=bef[x]; bef[x]=0; pre[next[x][0]]=0; next[x][0]=0; pushup(x); } void change(int x,int y,int val) { access(y); for(y=0;x;x=bef[x]) { splay(x); if(!bef[x]) { key[x]+=val; update_add(y,val); update_add(next[x][1],val); return; } pushdown(x); pre[next[x][1]]=0; bef[next[x][1]]=x; next[x][1]=y; pre[y]=x; bef[y]=0; y=x; pushup(x); } } int query(int x,int y) { access(y); for(y=0;x;x=bef[x]) { splay(x); if(!bef[x]) { return max(key[x],max(maxn[next[x][1]],maxn[y])); } pushdown(x); pre[next[x][1]]=0; bef[next[x][1]]=x; next[x][1]=y; pre[y]=x; bef[y]=0; y=x; pushup(x); } } }lct; struct s { int u,v,next; }edge[N<<1]; int head ,cnt; void add(int u,int v) { edge[cnt].u=u; edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++; } void bfs(int u) { queue<int>q; memset(vis,0,sizeof(vis)); vis[u]=1; q.push(u); while(!q.empty()) { u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(!vis[v]) { lct.bef[v]=u; vis[v]=1; q.push(v); } } } } int main() { int n; while(scanf("%d",&n)!=EOF) { int i; cnt=0; memset(head,-1,sizeof(head)); for(i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); add(u,v); add(v,u); } lct.init(); for(i=1;i<=n;i++) { scanf("%d",&lct.key[i]); } bfs(1); int q; scanf("%d",&q); while(q--) { int op,x,y; scanf("%d%d%d",&op,&x,&y); if(op==1) { if(lct.getroot(x)==lct.getroot(y)) { printf("-1\n"); } else lct.link(x,y); } else if(op==2) { if(x==y||lct.getroot(x)!=lct.getroot(y)) { printf("-1\n"); } else lct.cut(x,y); } else if(op==3) { int z; scanf("%d",&z); if(lct.getroot(y)!=lct.getroot(z)) { printf("-1\n"); } else lct.change(y,z,x); } else { if(lct.getroot(x)!=lct.getroot(y)) { printf("-1\n"); } else printf("%d\n",lct.query(x,y)); } } printf("\n"); } }
相关文章推荐
- C#中要使ListBox使用AddRange()时,能够触发SelectedValueChanged事件
- New THUer | 如何提高科研效率
- 求序列中满足Ai < Aj > Ak and i < j < k的组数 树状数组 HIT 2275 Number sequence
- 移动手机组态软件UI设计思路探讨
- Android Download机制详解(一)DocumentUI部分
- 全面解读远丰BBCbuilder系统五大优势
- ElabBuilder:实验室里的电子商务
- UITableViewCell和手势共存的问题
- iOS7与iOS8在UIFont上的差异
- easyui 之 datagrid动态列与列宽自适应
- UIViewController
- UICollectionView 集合视图基本使用
- STL priority_queue用法
- 一点点关于JS的东西:EasyUI布局+下拉框之个人简单使用
- 优化UITableView性能
- UI - UIScrollView和UIPageControl
- deque 双向队列
- ural 1742. Team building
- iOS中的UIView的基本属性1
- iOS中的UILabel