Cube Stacking 题目链接
题目描述:
Farmer John and Betsy are playing a game with N (1 <= N <= 30,000)identical cubes labeled 1 through N. They start with N stacks, each containing a single cube. Farmer John asks Betsy to perform P (1<= P <= 100,000) operation. There are two types of operations:
moves and counts.
- In a move operation, Farmer John asks Bessie to move the stack containing cube X on top of the stack containing cube Y.
- In a count operation, Farmer John asks Bessie to count the number of cubes on the stack with cube X that are under the cube X and report that value.
Write a program that can verify the results of the game.
输入:
-
Line 1: A single integer, P
-
Lines 2…P+1: Each of these lines describes a legal operation. Line 2 describes the first operation, etc. Each line begins with a ‘M’ for a move operation or a ‘C’ for a count operation. For move operations, the line also contains two integers: X and Y.For count operations, the line also contains a single integer: X.
Note that the value for N does not appear in the input file. No move operation will request a move a stack onto itself.
输出:
Print the output from each of the count operations in the same order as the input file.
输入样例:
6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4
输出样例:
1
0
2
此题需要用到并查集,关于并查集,请先看这篇文章,超有爱的并查集
题解:
题目大意,两个人在玩叠箱子游戏,这个游戏有两个操作。
1.M x y 代表把x所在的一列整体放倒y所在一列之上
2.C x 代表数一下x下方有几个箱子
思路:用并查集,需要稍加改动,需要用到三个数组
fa[i]代表i的父亲结点
son[i]代表包括i结点在内的其子树结点的个数
dis[i]表示i点到根结点的距离
在合并函数过程中不断进行路径压缩,并不断更新dis值,dis[i]+=dis[fa[i]]
查找某一个点x下边有几个点时,只用求出x根结点所在子树的结点个数-x到根结点的距离-1
即son[Find(x)]-dis[x]-1.
配一张图加深理解。
AC代码
#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 30005
int n,x,y;
int fa[MAX],son[MAX],dis[MAX];
// fa父结点 son当前节点子树大小 dis当前节点到根结点距离
inline void init()
{
for(int i=1;i<=MAX;i++)
{
fa[i]=i;
son[i]=1;
}
}
int Find(int t)
{
if(fa[t]==t)
return t;
int tp=fa[t];
fa[t]=Find(fa[t]);
dis[t]+=dis[tp]; //当前点到根结点的距离+=父结点到根结点的距离
return fa[t]; //路径压缩
}
void join(int x,int y)
{
int rx=Find(x);
int ry=Find(y);
if(rx!=ry)
{
fa[ry]=rx;//rx所在的子树放到ry所在子树之上
dis[ry]=son[rx];//ry到rx的距离就是rx所在子树的结点个数
son[rx]+=son[ry];//rx所在子树结点个数要加上ry这一棵树子树
}
}
int main(void)
{
scanf("%d",&n);
init();
char c;
for(int i=1;i<=n;i++)
{
getchar();
scanf("%c",&c);
if(c=='M')//合并
{
scanf("%d%d",&x,&y);
join(x,y);
}
else
{
scanf("%d",&x);
printf("%d\n",son[Find(x)]-dis[x]-1);
}
}
return 0;
}