题意:初始时有N堆砖块,每堆有一个(编号为1-N)。现在有q个操作,
操作分2种:
M X Y 将含编号X的那堆放置在编号为Y堆的上方
C X 含编号为X的砖块下方有多少个砖块
思路:在普通并查集的基础上加了两个变量:sum,top。用sum去维护某砖块下方的砖块数(代码实现过程中,实际上当前结点的sum值只记录到了它的当前父亲结点fa处的砖块个数,所以查询时需要先更新一下);top维护每个砖块所在位置最上方的砖块编号,因为每次进行第一种操作时,是把X所在的那一堆砖块放在Y所在那一堆砖块中最高砖块上
实际上我们字也只需要更新记录每一个父亲结点的top值。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int manx=3e4+10;
struct node
{
int fa,sum,top;
node()
{
sum=0;
}
}p[manx];
int find(int x)//查找根结点
{
if(x==p[x].fa)return x;
int temp=find(p[x].fa);
p[x].sum+=p[p[x].fa].sum;
//注意带权并查集中记录权值的变量都是在回溯的过程中更新的
return p[x].fa=temp;
}
int main()
{
char ope[2];
int n,x,y;
scanf("%d",&n);
for(int i=1;i<=manx;i++)
{
p[i].fa=i;
p[i].top=i;
}
while(n--)
{
scanf("%s",ope);
if(ope[0]=='M')
{
scanf("%d%d",&x,&y);
int fx=find(x);
int fy=find(y);
if(fx==fy)
continue;
p[fx].fa=p[fy].top;
p[fx].sum=1;
p[fy].top=p[fx].top;
}
else
{
scanf("%d",&x);
find(x);
printf("%d\n",p[x].sum);
}
}
}