LA3027

来源:互联网 发布:图知科技 编辑:程序博客网 时间:2024/06/05 08:13

题目链接

简介:
有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;}