zoukankan      html  css  js  c++  java
  • 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
    ",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!
  • 相关阅读:
    hdu 1199 Color the Ball 离散线段树
    poj 2623 Sequence Median 堆的灵活运用
    hdu 2251 Dungeon Master bfs
    HDU 1166 敌兵布阵 线段树
    UVALive 4426 Blast the Enemy! 计算几何求重心
    UVALive 4425 Another Brick in the Wall 暴力
    UVALive 4423 String LD 暴力
    UVALive 4872 Underground Cables 最小生成树
    UVALive 4870 Roller Coaster 01背包
    UVALive 4869 Profits DP
  • 原文地址:https://www.cnblogs.com/ACMessi/p/4837265.html
Copyright © 2011-2022 走看看