POJ1988 Cube Stacking 【并查集】
题目链接:http://poj.org/problem?id=1988
这题是教练在ACM算法课上讲的一道题,当时有地方没想明白,现在彻底弄懂了。
题目大意:n代表有n个石头,M a, b代表将a石头所在的集合放在b石头所在的所有集合的上方。C a代表询问a石头下方有多少个石头。
思路:
1.一开始我是想用一个 num 数组来表示每块石头下方有多少个石头,然后直接用并查集来写,但是发现最终不能实现,因为只用一个num数组只能保证每个集合的最顶端的石头num值是正确的。
2.正解是用一个 dis 数组代表每块石头到根节点石头的距离,num数组代表每块石头所在集合的石头总数,最终答案就是 num[find(a)] - dis[a] - 1;
3.需要注意的地方是 先查找根节点 后更新dis以及num,因此在查询某一块石头下面有多少石头时,还需要进行一次 find 来更新一下路径上石头的dis。
代码里的注释写的很详细
代码:
注意:数据好像比题面给的大,数组要开大点。
#include<iostream> //用cin输入无视空格和回车,方便判断操作
using namespace std; int num[], pre[], dis[]; int find(int x)
{
if(pre[x] == x)
return x;
else
{
int root = find(pre[x]);
dis[x] += dis[pre[x]];//下面的块中点到新根节点的距离为 原来的距离dis[x]加上被更新过的dis[root] = num[x]的距离
pre[x] = root;
return pre[x];
}
} int main()
{
cin.sync_with_stdio(false);//关闭cin同步加速,但读入只能用cin了
int n;
cin >> n;
for(int i = ; i <= n; i ++)
{
pre[i] = i;
dis[i] = ;//到根节点的距离
num[i] = ;//每个块中包含的点数目
}
while(n --)
{
char ch;
cin >> ch;
if(ch == 'M')
{
int a, b;
cin >> a >> b;
int x = find(a), y = find(b);//此时的find只是找到根节点,find()函数中各点dis值没有改变,因为此时根节点的dis为0
if(x != y)
{//注意顺序
dis[y] = num[x];//这里才给根节点的dis值进行了更新,所以下次还需要调用一次find才能维护各点的dis值
num[x] += num[y];//以x为根节点的块中数目更新为 以x和y为根节点的两个块中点的数目之和
pre[y] = x;
}
}
else if(ch == 'C')
{
int a;
cin >> a;
int x = find(a);//查询之前还需要进行一次 find 来更新块中各点的dis值
printf("%d\n", num[x] - dis[a] - );
}
}
return ;
}
POJ1988
POJ1988 Cube Stacking 【并查集】的更多相关文章
- POJ1988(Cube Stacking)--并查集
题目链接:http://poj.org/problem?id=1988 题意:有n个元素,开始每个元素各自在一个栈中,有两种操作,将含有元素x的栈放在含有y的栈的顶端,合并为一个栈. 第二种操作是询问 ...
- poj.1988.Cube Stacking(并查集)
Cube Stacking Time Limit:2000MS Memory Limit:30000KB 64bit IO Format:%I64d & %I64u Submi ...
- poj1988 Cube Stacking 带权并查集
题目链接:http://poj.org/problem?id=1988 题意:有n个方块,编号为1-n,现在存在两种操作: M i j 将编号为i的方块所在的那一堆方块移到编号为j的方块所在的那 ...
- poj1988 Cube Stacking(并查集
题目地址:http://poj.org/problem?id=1988 题意:共n个数,p个操作.输入p.有两个操作M和C.M x y表示把x所在的栈放到y所在的栈上(比如M 2 6:[2 4]放到[ ...
- poj1988 Cube Stacking
并查集的高效之处在于路径压缩和延迟更新. 在本题中需要额外维护子树的规模以及当前子树节点到跟的距离两个数组. 由于一个新的数必然是两棵树拼接而成,对于子树规模的更新直接相加即可, 对于节点到跟的距离: ...
- POJ1988 Cube stacking(非递归)
n有N(N<=30,000)堆方块,开始每堆都是一个方块.方块编号1 – N. 有两种操作: nM x y : 表示把方块x所在的堆,拿起来叠放到y所在的堆上. nC x : 问方块x下面有多少 ...
- POJ 1988 Cube Stacking(并查集+路径压缩)
题目链接:id=1988">POJ 1988 Cube Stacking 并查集的题目 [题目大意] 有n个元素,開始每一个元素自己 一栈.有两种操作,将含有元素x的栈放在含有y的栈的 ...
- bzoj3376/poj1988[Usaco2004 Open]Cube Stacking 方块游戏 — 带权并查集
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3376 题目大意: 编号为1到n的n(1≤n≤30000)个方块正放在地上.每个构成一个立方 ...
- POJ 1988 Cube Stacking( 带权并查集 )*
POJ 1988 Cube Stacking( 带权并查集 ) 非常棒的一道题!借鉴"找回失去的"博客 链接:传送门 题意: P次查询,每次查询有两种: M x y 将包含x的集合 ...
随机推荐
- mysql优化之SQL优化
https://www.cnblogs.com/binghou/p/9096610.html (SQL优化)
- [CCC 2016] 生命中的圆
题面 有这么一类题,它让你求一个0/1环经过T轮周围异或过程之后的样子. 周围异或即 a[i][k] = a[i-1][k-1] ^ a[i-1][k+1] ,其中第一维表示轮数,第二维表示位置. 千 ...
- 【CUDA 基础】5.6 线程束洗牌指令
title: [CUDA 基础]5.6 线程束洗牌指令 categories: - CUDA - Freshman tags: - 线程束洗牌指令 toc: true date: 2018-06-06 ...
- Restorator 2018 v3.90汉化注册版 含注册码汉化激活教程
链接:https://pan.baidu.com/s/1wfh5VQfNgbDr-glezL4faQ 提取码:y507
- CF1204A
CF1204A. BowWow and the Timetable 题意: 给你一个2进制数,求这个2进制数在10进制中的 $ 4^i $ 的个数. 解法: 其实就是 $ \ulcorner_{\lo ...
- 在Linux下使用rm -rf /*后会怎样?
每个工作过的码农,也许不知道分布式,也许不知道高并发,但想必都知道这句鼎鼎大名的代码.本人对此也是比较好奇的,不妨用虚拟机试试看 首先是普通角色: 普通角色把拥有权限的文件全都删掉了后,其他文件的提示 ...
- SpringMVC和AJAX交互
在实际开发中我们经常需要前后台交互,那么springmvc与ajax之间交互这里记录下在实际开发中遇到的细节问题. jsp页面: <fieldset id="login" s ...
- Linux中soft nproc 、soft nofile和hard nproc以及hard nofile配置
Linux中soft nproc .soft nofile和hard nproc以及hard nofile配置 "soft" 和 "hard" 的区别 soft ...
- Java-Unsafe
Unsafe 是 sun.misc 包下的一个类,可以直接操作堆外内存,可以随意查看及修改 JVM 中运行时的数据,使 Java 语言拥有了类似 C 语言指针一样操作内存空间的能力. Unsafe 的 ...
- 【VMWare】虚拟机启动遇到黑屏,在命令行窗口输入netsh winsock reset并不管用 重新启动客户机就好了
现象:虚拟机启动后是莫名其妙的黑屏,而且它上面安装的MySql也无法访问了. 处置:上网百度方案,看到大多数网文推荐:“以管理员身份打开cmd,输入netsh winsock reset,然后重启机器 ...