给你编号从1到30000块砖,有2种操作:
1.M a b 表示把a放在b的上面。
还有一种情况是:假如1的下面还有一个2,3的下面还有一个4,那么move1,3的意思就是把1所在的全部立方体放在3全部立方体的上面,而且保持原来1和3所在堆的立方体的顺序。移动后从上到下依次为1,2,3,4.且只能是这一种情况
2.count a 表示询问a下面有几块砖
带权值的并查集
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 30030
using namespace std;
long long high[maxn],f[maxn],num[maxn];//f记录上一层,high记录下面有几块砖,num记录以i为根的树子节点个数 (深度)
void init()//初始化
{
for(int i=0;i<maxn;i++)
{
f[i]=i;
high[i]=0;//根节点的高度为0
num[i]=1;
}
}
int find(int x)
{
if(x==f[x]) return f[x];
int r=f[x];
f[x]=find(f[x]);
high[x]+=high[r];//距根节点的距离
return f[x];//x的根节点
}
void unio(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx==fy) return;
high[fx]=num[fy];//原根节点的高度等于另一树的高度
f[fx]=fy;//fx的根节点变为fy
num[fy]+=num[fx];//新树的高度等于原两树深度之和
num[fx]=0;//旧根删除高度
}
int main()
{
int t,n,m;
char s[5];
scanf("%d",&t);
init();
int maxm=0;
while(t--)
{
scanf("%s",&s);
if(s[0]=='M')
{
scanf("%d%d",&n,&m);
unio(n,m);
}
else
{
scanf("%d",&n);
find(n);//查询中会计算high[x]
printf("%lld\n",high[n]);
}
}
return 0;
}