• 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!
  • 相关阅读:
    2021 CCPC 桂林站 补题
    2021 ICPC 上海 流水账
    2021 ICPC 沈阳 补题
    vi中的多行注释和取消注释
    查询列表可筛选可模糊查询的写法
    mybatisplus逻辑删除deleted
    @JsonFormat
    @Component类相互引用的加载顺序
    Chrome浏览器嗅探方法
    DataAdapter.FillSchema 方法
  • 原文地址:https://www.cnblogs.com/ACMessi/p/4837265.html
Copyright © 2020-2023  润新知