是一道关于并查集的题,每个结点处多了两个属性,一个是该点以上有多少个点,即up属性。另一个是该点下面有多少个点,即down属性,查找和合并操作时,把up和down属性也一起更新就可以了。。。。。题目:
Building Block
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1061 Accepted Submission(s): 311
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 <iostream>
#include <cstdio>
using namespace std;
#define M 30010
int up[M],down[M],p[M];
void init(){
for(int i=0;i<M;++i){
up[i]=0;
down[i]=1;
p[i]=i;
}
}
int find(int x){
int t=p[x];
if(t!=x){
p[x]=find(t);
up[x]+=up[t];//更新该点到父节点的距离
}
return p[x];
}
void unionset(int x,int y){
int px=find(x);
int py=find(y);
if(px!=py){
p[py]=px;
up[py]=down[px];
down[px]+=down[py];
}
}
void count(int x){
int root=find(x);//更新x点到最远祖先的距离
printf("%d\n",down[root]-up[x]-1);
}
int main(){
//freopen("1.txt","r",stdin);
int numcase;
while(~scanf("%d",&numcase)){
init();
char que;
int x,y;
while(numcase--){
cin>>que;
if(que=='M'){
scanf("%d%d",&x,&y);
unionset(x,y);
}else{
scanf("%d",&x);
count(x);
}
}
}
return 0;
}