hdoj 2818 Building Block(加权并查集)
2016-07-22 20:10
429 查看
Building Block
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4856 Accepted Submission(s): 1505
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
2009 Multi-University Training
Contest 1 - Host by TJU
题意:john 正在玩积木,有N个积木编号为1、、、N,分成N堆,每堆只包含一个积木,然后做P次操作,操作分为2种,
M X Y:把包含X的一堆放到包含Y的一堆上,如果XY同在一堆上,不做处理
C X:计算出X积木下边有多少个积木
每次遇到C操作,输出数量
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 30005; int pre[maxn], count[maxn], under[maxn]; //count[i]记录i所在堆的木块总数,under记录i木块下方的木块数量 int Find(int x) { if(pre[x] == x) return x; else { int t = Find(pre[x]); //递归找到根 under[x] += under[pre[x]]; //从根下第一个节点开始回溯更新节点的under数, //每个节点的under数即为原来的加上根节点在join时更新的under, //即加上b堆的总数,因为b堆都在a下面 pre[x] = t; return t; } } //join只把两个堆连上,即将y的根节点作为x的根节点的父节点 void join(int x, int y) { int a = Find(x), b = Find(y); //各一次Find,会x,y到根节点的under更新并压缩路径。 if(a != b) { under[a] = count[b]; //a接到了b上,under[a]即为b的总数 count[b] += count[a]; //同时更新b的总数 pre[a] = b; } } int main(void) { int n; while(cin >> n) { for(int i = 0; i < maxn; i++) { pre[i] = i; under[i] = 0; count[i] = 1; } while(n--) { char cmd; cin >> cmd; if(cmd == 'M') { int a, b; scanf("%d%d", &a, &b); join(a, b); } else { int a; scanf("%d", &a); Find(a);<span style="white-space:pre"> //还需自己把a到它的根节点的每个节点的under更新一下</span> printf("%d\n", under[a]); } } } return 0; }
相关文章推荐
- 如何在 Ubuntu Linux 中使用 RAR 文件
- C#数据结构之顺序表(SeqList)实例详解
- Lua教程(七):数据结构详解
- 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解
- C#使用DeflateStream解压缩数据文件的方法
- C#数据结构之队列(Quene)实例详解
- C#数据结构揭秘一
- C# 利用ICSharpCode.SharpZipLib实现在线压缩和解压缩
- C#数据结构之单链表(LinkList)实例详解
- C#使用WinRar命令进行压缩和解压缩操作的实现方法
- C#调用WinRar执行rar、zip压缩的方法
- 数据结构之Treap详解
- C语言压缩文件和用MD5算法校验文件完整性的实例教程
- C#实现页面GZip或Deflate压缩的方法
- C#使用iCSharpcode进行文件压缩实现方法
- C#图片切割、图片压缩、缩略图生成代码汇总
- C#实现压缩HTML代码的方法
- Asp.net在线备份、压缩和修复Access数据库示例代码
- 用C语言举例讲解数据结构中的算法复杂度结与顺序表
- C#数据结构之堆栈(Stack)实例详解