并查集——nkoj2281方块游戏

方块游戏

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);
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值