[bzoj3376] Cube Stacking 方块游戏

Description

约翰和贝茜在玩一个方块游戏.编号为1到n的n(1≤n≤30000)个方块正放在地上.每个构成一个立方柱.

游戏开始后,约翰会给贝茜发出P(1≤P≤100000)个指令.指令有两种:

  1. 移动(M):将包含X的立方柱移动到包含Y的立方柱上.

  2. 统计(C):统计名含X的立方柱中,在X下方的方块数目.

写个程序帮贝茜完成游戏.

Input

第1行输入P,之后P行每行输入一条指令.形式为“M X Y”或者“C X”

输入保证不会有将立方柱放在自己头上的指令.

Output

每一行,对于每个统计指令,输出其结果.

Sample Input

6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4

Sample Output

1
0
2

Source

[Usaco2004 Open]

题解

带权并查集:用\(f1[x]\)代表\(x\)最上面的方块编号,用\(f2[x]\)代表\(x\)最下面的方块编号,用\(dis[x]\)代表\(x\)距离最上面的方块的距离,\(dis[f2[x]]-dis[x]\)即为答案。

#include<bits/stdc++.h>
using namespace std;

const int N=30001;
int f1[N],f2[N],dis[N];

int Find(int x)
{
	if(x!=f1[x])
	{
		int Res=f1[x];
		f1[x]=Find(Res),
		f2[x]=f2[Res],
		dis[x]+=dis[Res];
	}
	return f1[x];
}
void Union(int x,int y)
{
	int f1x=Find(x),f1y=Find(y);
	f1[f1y]=f1x,dis[f1y]=dis[f2[x]]+1,f2[f1x]=f2[f1y];
	Find(f2[y]);
}

int main()
{
	int P,x,y; char c;
	for(int i=1;i<N;++i) f1[i]=f2[i]=i;
	for(scanf("%d\n",&P);P;--P)
	{
		scanf("%c",&c);
		if(c=='M') scanf("%d%d\n",&x,&y),Union(x,y);
		else scanf("%d\n",&x),Find(x),printf("%d\n",dis[f2[x]]-dis[x]);
	}
	return 0;
}
posted @ 2019-08-21 09:09  OItby  阅读(169)  评论(0编辑  收藏  举报