方块游戏
Description
FJ 和贝茜 用 N (1 <= N <= 30,000)块相同的小立方块玩游戏,小方块编号为 1..N。开始时,小方块都单独分开的, 每个看成一个柱子, 即有 N 柱子。 FJ 要 贝茜做 P(1 <= P <= 100,000) 个操作,操作有两种类型:
(1) FJ 要求贝茜把X 号方块所在的柱子放到 Y号所在的柱子上面,成一个新柱子。
(2)FJ 要求贝茜计算 X 号方块所在柱子,它下面有多少个小方块。
请编个程序,帮助贝茜计算。
Input
*第一行:一个整数 P
*第 2..P+1行:第 i+1行表示第 i个FJ要求的合法操作。如果这行以'M'开头,后面有两个整数 X,y 表示要进入(1)操作。
如果这行以'C'开头,后面有一个整数 X,表示要求计算 X所在柱子下面的方块个数。
注:所有操作都是合法的。N 并没有出现在输入文件中。
Output
依次要求计算的值,每次一行。
Sample Input
6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4
Sample Output
1
0
2
Hint
样例说明:
6 : 6 个操作
M 1 6 : 1,6 / 2 / 3 / 4 / 5 把 1放在 6 上面。
C 1 : 输出:1
M 2 4 : 1,6 / 2,4 / 3 / 5
M 2 6 : 2,4,1,6 / 3 / 5
C 3 : 输出 :0
C 4 : 输出: 2
#include<cstdio>
#include<iostream>
using namespace std;
int count[50005],before[50005],father[50005];
//count[x]记录以x为开头的柱子长度,before[x]是x所在柱子x上面的方块个数
int getfather(int x)//找爸爸,同时更新before和count
{
int dad;
if(father[x]==x)return x;
dad=getfather(father[x]);
before[x]=before[x]+before[father[x]];//这句必须放在上一句后面
father[x]=dad;
return father[x];
}
void merge(int x,int y)//把x柱子放到y柱子上面
{
x=getfather(x);
y=getfather(y);
father[y]=x;
before[y]=before[y]+count[x];
count[x]=count[x]+count[y];
}
int main(){
int p,x,y,t,i,j,k;
char ch;
cin>>p;
for(i=1;i<=30005;i++)
{
father[i]=i;
count[i]=1;
}
for(i=1;i<=p;i++)
{
for(ch=getchar();ch!='M'&&ch!='C';)ch=getchar();
if(ch=='M')
{
scanf("%d%d",&x,&y);
merge(x,y);
}
else
{
scanf("%d",&x);
y=getfather(x);
printf("%d\n",count[y]-before[x]-1);
}
}
}