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.
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之下有多少个方块
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]; } }