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!
  • 相关阅读:
    第二节:Android APP自动化测试之环境配置以及脚本设计(课工场)
    第一节:Appium介绍(课工场)
    Dockerfile 相关命令
    Nginx 原理及与 Apache 对比
    Windows 环境配置 Nginx
    Linux 命令大全(十九)——性能优化及常见问题
    Linux 命令大全(十八)——压缩打包
    Linux 命令大全(十七)——VI/VIM编辑器
    Linux 命令大全(十六)——计划任务
    Linux 命令大全(十五)——配置文件
  • 原文地址:https://www.cnblogs.com/ACMessi/p/4837265.html
Copyright © 2011-2022 走看看