Cube Stacking

Cube Stacking

Time Limit:2000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u
Submit Status

Description

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. 

Input

* 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. 

Output

Print the output from each of the count operations in the same order as the input file. 

Sample Input

6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4

Sample Output

1
0
2

 并查集:ran[x] 表示 在x下面的立方体数,sum[x]表示x所在堆的总立方体数,随着立方体的叠放,sum值只记载在根节点处,在unite()中,ran值也只是记载在fx上,容易理解ran[fx] += sum[fy];在之后find()中再将一个个节点经行更新ran[x] += ran[fx];

#include<cstdio>
#include<algorithm>
#include<cstring>
const int maxn = 3e4+5;
using namespace std;
int pre[maxn];
int ran[maxn];
int sum[maxn];
void init(){
    for(int i = 1; i <= maxn; i++){
        pre[i] = i;
        ran[i] = 0;
        sum[i] = 1;
    }
}
int find(int x){
    if(pre[x] == x)
        return pre[x];
    int fx = pre[x];
    pre[x] = find(pre[x]);
    ran[x] += ran[fx];
    return pre[x];
}
void unite(int x,int y){
    int fx = find(x);
    int fy = find(y);
    pre[fx] = fy;
    ran[fx] += sum[fy];
    sum[fy] += sum[fx];
}
int main(){
    int p,x,y;
    char ch[2];
    init();
    scanf("%d",&p);
    while(p--){
        scanf("%s",ch);
        if(ch[0] == 'M'){
            scanf("%d%d",&x,&y);
            unite(x,y);
        }
        else {
            scanf("%d",&x);
            int tep = find(x);
            printf("%d\n",ran[x]);
        }
    }
    return 0;
}

 另外,通过这道题终于懂了并查集的find()函数,原来我之前都是一知半解= =!

举个例子说明一下:  

int find(int x){
    if(pre[x] == x)
        return pre[x];
    int fx = pre[x];
    pre[x] = find(pre[x]);
    ran[x] += ran[fx];
    return pre[x];
}
1 -> 2 -> 3 -> 4 -> 5;
x = 1, fx = 2; -> x = 2, fx = 3; -> x = 3, fx = 4; -> x = 4, fx = 5; -> x = 5, fx = 5;

pre[4] = pre[5](5); -> pre[3] = pre[4](5); -> pre[2] = pre[3](5); -> pre[1] = pre[2](5);

ran[4] += ran[5]; -> ran[3] += ran[4]; -> ran[2] += ran[3]; -> ran[1] += ran[2];

这样就形成了一颗高度为2的树,除根节点外全部节点指向根节点,搜索起来减少了不少的复杂度,膜拜!
而ran值也在其中是从根节点经行更新;
并查集真是so cool!
posted @ 2015-09-25 09:49  Tobu  阅读(237)  评论(0编辑  收藏  举报