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 02
此题是并查集的运用,题目的意思就是 在后面的数字上面放砖块(把一堆集合 移到另一堆的上面),
当为C的时候,求C还没数字下面的专块数目, 若是同个集合 就不要加高度了 所以得考虑根的长度
所以多定义一个高度的数组,还时刻更新
代码如下
#include<stdio.h> #include<string.h> char ch[2]; int fu[30002]; int gaodu[30002]; int di[30002]; int me(int x) { if(x==fu[x]) return fu[x]; else { int z=me(fu[x]); di[x]+=di[fu[x]]; //x的高度 就是父结点下面的个数加他到父节点的个数 return fu[x]=z; } } int main() { int bbs; int x,y; scanf("%d",&bbs); for(int i=0;i<=30002;i++) { fu[i]=i; gaodu[i]=1; di[i]=0; } while(bbs--) { scanf("%s",ch); if(ch[0]=='M') { scanf("%d%d",&x,&y); int p=me(x); int q=me(y); if(p==q) continue; di[p]=gaodu[q]; //p下面的个数就是q的高度 gaodu[q]=gaodu[q]+gaodu[p]; //此刻q所在集合的高度为二者高度之和 fu[p]=q; //二者合并 } else { scanf("%d",&x); me(x); printf("%d\n",di[x]); } } return 0; }