Building Block
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4269 Accepted Submission(s): 1334
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.
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
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 30005;
int fa[maxn];//父亲结点
int low[maxn];//该点以下的砖块
int high[maxn];//包含该砖块的并查集中包括的砖块总和
void init()
{
for(int i = 0 ; i < maxn; i++)
{
fa[i] = i;
low[i] = 0;
high[i] = 1;
}
}
int Find(int x)
{
if(x != fa[x])
{
int root = Find(fa[x]); //递归的时候更新low数组,需要细细体会。
low[x] += low[fa[x]];
return fa[x] = root;
}
else
return x;
}
int main()
{
int P,x,y;
char c;
scanf("%d%*c",&P);
init();
while(P--)
{
scanf("%c",&c);
if(c == 'M')
{
scanf("%d%d%*c",&x,&y); //后面的%*c是为了消除换行符
int fx = Find(x),fy = Find(y);
if(fx == fy) continue;
fa[fx] = fy;
low[fx] = high[fy];
high[fy] += high[fx];
}
else if(c == 'C')
{
scanf("%d%*c",&x);
Find(x);
cout << low[x] << endl;
}
}
return 0;
}