初始时每个堆就一个方块,如果碰到指令M,那么就是把x的堆放到y的堆上,那么我们把不动的堆,也就是y当作根,把x解到y上,那么x堆的根结点的under[rootx]改成
y堆的sum[rooty],因为x堆下面最起码有sum[rooty]的方块,y的每个方块的under是不用更新的,因为它没有变,而x堆的方块则需要更新,更新的方法就是如果你要知道
p下面有多少个节点时,从p开始去寻找根结点,然后把找到的每个节点的under值都相加。因为这条路上的几点都是之前的根结点,他们之前移动时,已经被更新成了sum[rooty],也就是被移动到的堆的总结点数,所以这一路上相加之后,就是p的under值了。
这种思路解题的最关键因素时,需要把不动的结点当做根结点,动的结点接上去,并把动的堆的根结点的under值更新为不动堆的总结点数,方便相加。
//
// main.cpp
// Richard
//
// Created by 邵金杰 on 16/7/1.
// Copyright © 2016年 邵金杰. All rights reserved.
//
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=30000+1000;
int pa[maxn],sum[maxn],under[maxn];
int getroot(int a)
{
if(pa[a]==a) return a;
int t=getroot(pa[a]);
under[a]+=under[pa[a]];
pa[a]=t;
return pa[a];
}
void merge(int a,int b)
{
int root1=getroot(a);
int root2=getroot(b);
if(root1==root2) return ;
pa[root2]=root1;
under[root2]=sum[root1];
sum[root1]+=sum[root2];
}
int main()
{
int t,x,y;
char cmd[10];
cin>>t;
for(int i=0;i<maxn;i++) {sum[i]=1;pa[i]=i;under[i]=0;}
while(t--)
{
scanf("%s",cmd);
if(cmd[0]=='M') {cin>>x>>y;merge(x,y);}
else {cin>>x;getroot(x);cout<<under[x]<<endl;}
}
}