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的集合 ...
随机推荐
- 解决ubuntu安装软件has install-snap change in progress错误
解决ubuntu安装软件has install-snap change in progress错误 2018年05月06日 13:45:39 山间明月江上清风_ 阅读数:14316 标签: ubunt ...
- MSMQ使用
Message Message是MSMQ的数据存储单元,我们的用户数据一般也被填充在Message的body当中,因此很重要,让我们来看一看其在.net中的体现,如图: 在图上我们可以看见,Messa ...
- 灰度变换,gama变换,对数,反对数变换
学习DIP第2天 灰度变换,及按照一定规则对像素点的灰度值进行变换,变换的结果可以增强对比度,或者达到其他的效果(例如二值化,或者伽马变换),由于灰度变换为针对单个像素点的灰度值进行变换,素以算法复杂 ...
- 学习Javascript的编程风格
Javascript编程风格 Douglas Crockford是Javascript权威,Json格式就是他的发明. 去年11月他有一个演讲(Youtube),谈到了好的Javascript编程 ...
- Jmeter(十三)阶梯式压测
阶梯式压测,就是对系统的压力呈现阶梯性增加的过程,每个阶段压力值都要增加一个数量值,最终达到一个预期值.然后保持该压力值,持续运行一段时间. Jmeter中有个插件可以实现这个场景,这个插件就是:Co ...
- axios拦截器使用方法
vue中axios获取后端接口数据有时候需要在请求开始时显示loading,请求结束后隐藏loading,这时候到每次调接口时都写上有点繁琐,有时候还会漏写. 这时候axios的拦截器就起了作用,我们 ...
- Atcoder ABC138
Atcoder ABC138 A .Red or Not 一道网速题. 大于3200输出原字符串,否则就输出red. #include<iostream> #include<cstd ...
- php 设置error_reporting(0)和ini_set('display_errors', 0)之后,还是显示错误
php 5.4 apache 2.2 关闭错误报告和错误显示 依然会显示错误 按照我的理解,error_reporting(0)之后就应该不会显示错误了,这是怎么回事? 后来我又试着在php.ini者 ...
- 火车购票问题(16年ccf)
火车购票问题(16年ccf) 问题描述 请实现一个铁路购票系统的简单座位分配算法,来处理一节车厢的座位分配. 假设一节车厢有20排.每一排5个座位.为方便起见,我们用1到100来给所有的座位编号,第一 ...
- Python —— sklearn.feature_selection模块
Python —— sklearn.feature_selection模块 sklearn.feature_selection模块的作用是feature selection,而不是feature ex ...