zoukankan      html  css  js  c++  java
  • hdu 2818 Building Block(并查集,有点点复杂)

    Building Block

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 5811    Accepted Submission(s): 1790

    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.
     
    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
    0
    2
     
    Source
    Recommend
    gaojie   |   We have carefully selected several similar problems for you:  2819 2817 2824 2821 2820 
     
    题解:

    因为要查询x的下面有多少blocks,所以我们在普通并查集的基础上在维护两个域num[x]和under[x],分别表示x所在堆的大小以及x下面的元素。

    在合并的时候,我们分别取x,y的堆的最下面一块,也就是他们的根a,b.a和b相等就不用处理了。如果不相等,那么就让fa[a] = b.而在这之前,我们要维护size和under,所有x原来所在的堆的每个元素的under都要增加num[b],如果全都修改会超时,所以我们之修改under[a],把其它修改放在压缩里面,要查哪一个再更新。同时,为了方便我们只把size存在根上,也就是num[b]+=num[a],num[a] = 0。

    在find的时候,我们进行压缩,这时候更新under[x],under[x]+=under[fx]就可以了。

    注意:这题一直wa,原因是在刚开始赋值时,应该从0下标开始,然而题目中标号是从1号开始的,不懂。。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    int fa[30005],under[30005],num[30005];
    int p;
    char ch[5];
    int findfa(int k)
    {
        if (fa[k]==k) return k;
        int fa1=fa[k]; //找到之前的那个父亲,这个父亲的under值在后面find的过程中也会变,所以只要加之前的父亲节点的under就行了。
        fa[k]=findfa(fa[k]);
        under[k]+=under[fa1];
        return fa[k];
    }
    void uni(int x,int y)
    {
        int fx=findfa(x);
        int fy=findfa(y);
        if (fx!=fy)
        {
           under[fx]+=num[fy];
           num[fy]+=num[fx];
           num[fx]=0;
           fa[fx]=fy;
        }
        return;
    }
    
    int main()
    {
            for(int i=0;i<30005;i++)
            { fa[i]=i; under[i]=0; num[i]=1;}
    
            scanf("%d",&p);
            for(;p>0;p--)
            {
                scanf("%s",&ch);
                if (ch[0]=='M')
                {
                    int x,y;
                    scanf("%d%d",&x,&y);
                    uni(x,y);
                } else
                {
                    int x;
                    scanf("%d",&x);
                    findfa(x);
                    printf("%d
    ",under[x]);
                }
            }
    
        return 0;
    }
  • 相关阅读:
    项目成本管理(三)
    项目成本管理(二)
    项目成本管理(一)
    男士香水
    荷兰猛兽-梅尔文训练体能
    PP学习笔记-业务基础
    SAP入行就业
    PP学习笔记02
    BZOJ 3012: [Usaco2012 Dec]First! 字典树 + tarjan
    CF319E Ping-Pong 线段树 + vector + 思维
  • 原文地址:https://www.cnblogs.com/stepping/p/7217700.html
Copyright © 2011-2022 走看看