• hdu 2818(并查集,带权更新)


    Building Block

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


    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
     
    越来越觉得并查集牛了。。
     
    题目大意:有N个piles(按序编号),每次有两种操作:
    M x y 把包含x的一堆放到包含y的一堆上,如果xy同在一堆上,不做处理
    C x 询问在x之下有多少个方块
     
    题解:在以前的father和count(friend)之上再添加一个新的数组 under 表示当前结点的下面的pile的个数(我的理解是每个点带有一个权值为under[pos])
    under数组的更新:第一种是针对每次将x堆放在y堆上面时,under[x]= under[x]+count[y]
    第二种是求 a的根节点x与a之间的pile的个数,这里要利用find函数来进行递归,under[deep] = under[deep]+under[deep+1]
    最后回溯到a点时就可以将under[a]求出来了
     
    代码:
    import java.util.Scanner;
    
    public class Main {
        static int[] father;
        static int[] count;
        static int[] under;// 编号为i的Pile下面有多少个Piles
    
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            father = new int[30005];
            count = new int[30005];
            under = new int[30005];
            for (int i = 0; i < 30005; i++) {
                father[i] = i;
                count[i] = 1;
            }
            int n = sc.nextInt();
            while (n-- > 0) {
                String str = sc.next();
                if (str.equals("M")) {
                    int a = sc.nextInt();
                    int b = sc.nextInt();
                    int x = find(a); // 找到的是a堆最下面的pile x
                    int y = find(b); // 找到的是b堆最下面的pile y
                    if (x != y) {
                        father[x] = y;
                        under[x] += count[y]; // 根节点下面的pile就是y堆所有的个数
                        count[y] += count[x]; // 更新当前堆的pile的个数
                    }
                } else {
                    int a = sc.nextInt();
                    find(a);
                    System.out.println(under[a]);
                }
            }
    
        }
    
        private static int find(int a) {
            if (father[a] != a) {   //这步非常精彩 从 a点开始向下递归 ,每向下递归一层其上层就是等于 下层的under[dep+1]加上自己的under[dep]
                                    //到最后回溯到a点就把所有的都求出来了
                int tmp = find(father[a]);   
                under[a] += under[father[a]];
                father[a] = tmp;
            }
            return father[a];
        }
    }
  • 相关阅读:
    通过网页源代码看“饭否”的网站架构
    SD2.0课程等待时候的摘抄
    SD2.0阿里妈妈的研发过程
    转:编程8字专静谦筹悟慎透恒
    SD2.0第一天总体印象
    SD2.0《Web2.0网站性能调优实践》貌似是抄袭的文章
    SD2.02个课合成一个课
    SD2.0第2天总体印象
    variant
    [zz]C++程序员的阅读清单
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5320665.html
Copyright © 2020-2023  润新知