hdu 4010 Query on The Trees
Query on The Trees
http://acm.hdu.edu.cn/showproblem.php?pid=4010
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)
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!
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.
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.
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
题目大意:
写一种数据结构,支持以下操作:
1、如果x和y不在同一棵树中,在x和y之间连一条边
2、如果x和y在同一棵树中,同时x!=y,断掉x和y之间的边
3、如果x和y在同一棵树中,从x到y的路径上所有的点都+w
4、如果x和y在同一棵树中,输出从x到y路径上所有点的最大值
如果不满足“如果”条件,输出-1
直接上LCT
#include<cstdio> #include<cstring> #include<algorithm> #define N 300005 using namespace std; int n,fa[N],st[N],ch[N][2],maxn[N],tag[N],rev[N],key[N],top; int last[N],cnt,q[N]; struct edge{int to,next;}e[N<<1]; void insert(int u,int v) { e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt; e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt; } inline void up(int x) { maxn[x]=max(maxn[ch[x][1]],maxn[ch[x][0]]); maxn[x]=max(maxn[x],key[x]); } inline void down(int x) { if(rev[x]) { rev[x]^=1;rev[ch[x][1]]^=1;rev[ch[x][0]]^=1; swap(ch[x][0],ch[x][1]); } if(tag[x]) { if(ch[x][0]) maxn[ch[x][0]]+=tag[x],tag[ch[x][0]]+=tag[x],key[ch[x][0]]+=tag[x]; if(ch[x][1]) maxn[ch[x][1]]+=tag[x],tag[ch[x][1]]+=tag[x],key[ch[x][1]]+=tag[x]; tag[x]=0; } } inline bool isroot(int x) { return ch[fa[x]][1]!=x&&ch[fa[x]][0]!=x; } inline void rotate(int x) { int y=fa[x],z=fa[y],l,r; if(ch[y][0]==x) l=0; else l=1; r=l^1; if(!isroot(y)) { if(ch[z][0]==y) ch[z][0]=x; else ch[z][1]=x; } ch[y][l]=ch[x][r];ch[x][r]=y; fa[x]=z;fa[y]=x;fa[ch[y][l]]=y; up(y); } inline void splay(int x) { int t=0;st[++t]=x; for(int i=x;!isroot(i);i=fa[i]) st[++t]=fa[i]; for(int i=t;i;i--) down(st[i]); while(!isroot(x)) { int y=fa[x],z=fa[y]; if(!isroot(y)) { if(ch[y][0]==x^ch[z][0]==y) rotate(x); else rotate(y); } rotate(x); up(x); } } inline void access(int x) { int t=0; while(x) { splay(x); ch[x][1]=t; up(x); t=x;x=fa[x]; } } inline int findroot(int x) { access(x); splay(x); while(ch[x][0]) x=ch[x][0]; return x; } inline void make_root(int x) { access(x); splay(x); rev[x]^=1; } inline void link(int x,int y) { make_root(x); fa[x]=y; } inline void cut(int x,int y) { make_root(x); access(y); splay(y); ch[y][0]=fa[ch[y][0]]=0; up(y); } inline bool judge(int x,int y) { int a=findroot(x); int b=findroot(y); if(a==b) return true; return false; } inline void pre() { memset(fa,0,sizeof(fa)); memset(ch,0,sizeof(ch)); memset(maxn,0,sizeof(maxn)); memset(tag,0,sizeof(tag)); memset(rev,0,sizeof(rev)); memset(last,0,sizeof(last)); top=0; maxn[0]=-200000000; } int main() { while(scanf("%d",&n)!=EOF) { int x,y,p,z; pre(); for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); insert(x,y); } for(int i=1;i<=n;i++) { scanf("%d",&key[i]); maxn[i]=key[i]; } q[++top]=1; for(int k=1;k<=top;k++) { int now=q[k]; for(int i=last[now];i;i=e[i].next) if(e[i].to!=fa[now]) { fa[e[i].to]=now; q[++top]=e[i].to; } } int m; scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d",&p); if(p==1) { scanf("%d%d",&x,&y); if(!judge(x,y)) link(x,y); else printf("-1\n"); } else if(p==2) { scanf("%d%d",&x,&y); if(x!=y&&judge(x,y)) cut(x,y); else printf("-1\n"); } else if(p==3) { scanf("%d%d%d",&x,&y,&z); if(judge(y,z)) { make_root(y); access(z); splay(z); maxn[z]+=x; tag[z]+=x; key[z]+=x; } else printf("-1\n"); } else { scanf("%d%d",&x,&y); if(judge(x,y)) { make_root(x); access(y); splay(y); printf("%d\n",maxn[y]); } else printf("-1\n"); } } printf("\n"); } }
3个错误:
1、开始建树方法错误
错误代码:
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
if(x<y) swap(x,y);
fa[x]=y;
}
应该用遍历的方法建树
这个样不能保证只有一个根节点
2、更新答案错误
inline void up(int x)
{
maxn[x]=max(maxn[ch[x][1]],maxn[ch[x][0]]);
maxn[x]=max(maxn[x],key[x]);
}
漏了第2句,这也是key数组的作用
3、多组数据,top没有清0
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何调试 malloc 的底层源码
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端