简介:
有n个结点,初始时每个结点都是独立的,有两种操作:
I u v:把u的父节点设为v,距离为|u-v|%1000
E u:询问u到根节点的距离
分析:
题目只查询结点到根节点的距离,所以整棵树除了根节点不能变换之外,其他结点的位置可以任意变换
这恰好符合并查集的特点
为了快速回答询问,我们需要记录每个节点到父亲的距离d
在并查集的路径压缩的同时维护d
注意:
由于本题的合并操作指定了父节点和儿子结点,所以不能用按秩合并
tip
fa和d的初始化不要忘了
//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=20003;
int n,fa[N],d[N];
int find(int x)
{
if (fa[x]!=x)
{
int root=find(fa[x]);
d[x]+=d[fa[x]]; //维护d,此时的fa还是没有压缩的
fa[x]=root;
}
return fa[x];
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d",&n);
for (int i=1;i<=n;i++) fa[i]=i,d[i]=0; //初始化
char opt[2];
while (scanf("%s",&opt)!=EOF&&opt[0]!='O')
{
int u,w;
if (opt[0]=='I'){
scanf("%d%d",&u,&w);
fa[u]=w; //直接连接
d[u]=abs(u-w)%1000; //不要忘了计算距离
}
else{
scanf("%d",&u);
find(u); //在询问的时候路径压缩一次就可以了
printf("%d\n",d[u]);
}
}
}
return 0;
}