Building Block
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4611 Accepted Submission(s): 1433
Problem Description
John are playing with blocks. There are N blocks (1 <= N <= 30000) numbered 1...N。Initially, there are N piles, and each pile contains one block. Then John do some operations P times (1 <= P <= 1000000). There are two kinds of operation:
M X Y : Put the whole pile containing block X up to the pile containing Y. If X and Y are in the same pile, just ignore this command.
C X : Count the number of blocks under block X
You are request to find out the output for each C operation.
Input
The first line contains integer P. Then P lines follow, each of which contain an operation describe above.
Output
Output the count for each C operations in one line.
Sample Input
6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4
Sample Output
1
0
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4611 Accepted Submission(s): 1433
Problem Description
John are playing with blocks. There are N blocks (1 <= N <= 30000) numbered 1...N。Initially, there are N piles, and each pile contains one block. Then John do some operations P times (1 <= P <= 1000000). There are two kinds of operation:
M X Y : Put the whole pile containing block X up to the pile containing Y. If X and Y are in the same pile, just ignore this command.
C X : Count the number of blocks under block X
You are request to find out the output for each C operation.
Input
The first line contains integer P. Then P lines follow, each of which contain an operation describe above.
Output
Output the count for each C operations in one line.
Sample Input
6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4
Sample Output
1
0
2
题意:
使用并查集(路径压缩)实现,然后用num[X]表示X所在的那一堆总共多少个piles,ren[x]表示x之下有多少个piles。
首先,每次操作我们合并两个集合(如果原来在同一集合中除外),num[X]是每次操作可以直接实现的,就是把两堆的数目相加,很容易(初始值为1)。那么当某次移动操作发生时,首先确定x所在的那一堆最底部的X以及y所在那一堆最底部的Y,那么ren[X]的数目就是另外一堆piles的总数num[Y],有了这个条件,在接下去的操作中,就可以根据FIND(x)递归去一边寻找根一边更新其他未知的num[x]。
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
const int maxx=30005;
int par[maxx]; ///存放父亲结点
int ren[maxx];///存放x下的元素的个数
int num[maxx];///每堆上面的数目
void init()
{
for(int i=0; i<=maxx; i++)
{
par[i]=i;///初始化
ren[i]=0;/// 起初下面为0
num[i]=1; /// 每堆上面的数目为1
}
}
int find(int x)
{
if(par[x]==x)
{
return x;
}
else
{
int temp=find(par[x]);
ren[x]+=ren[par[x]];///更新每个结点下的数目(加上根节点下的数目)
par[x]=temp;
return par[x];
}
}
void unite(int a,int b)
{
a=find(a);
b=find(b);
if(a==b)
return ;
par[a]=b;
ren[a]=num[b];///更新a下面的数为b堆的数目
num[b]+=num[a];///b堆的数目更新为二者之和
num[a]=0;///合并后将a下的数目变为0
}
int main()
{
int n;
scanf("%d",&n);
getchar();
init();
char s[5];
for(int i=1; i<=n; i++)
{
scanf("%s",s);
if(s[0]=='M')
{
int a,b;
scanf("%d%d",&a,&b);
unite(a,b); ///合并
}
else if(s[0]=='C')
{
int x;
scanf("%d",&x);
find(x);
printf("%d\n",ren[x]);
}
}
return 0;
}