ACWing 238 银河英雄传说
最近带权并查集这块比较薄弱,直接看食物链看不懂,就老实一步步来了。
有一个划分为N列的星际战场,各列依次编号为1,2,…,N。
有N艘战舰,也依次编号为1,2,…,N,其中第i号战舰处于第i列。
有T条指令,每条指令格式为以下两种之一:
1、M i j,表示让第i号战舰所在列的全部战舰保持原有顺序,接在第j号战舰所在列的尾部。
2、C i j,表示询问第i号战舰与第j号战舰当前是否处于同一列中,如果在同一列中,它们之间间隔了多少艘战舰。
现在需要你编写一个程序,处理一系列的指令。
输入格式
第一行包含整数T,表示共有T条指令。
接下来T行,每行一个指令,指令有两种形式:M i j或C i j。
其中M和C为大写字母表示指令类型,i和j为整数,表示指令涉及的战舰编号。
输出格式
你的程序应当依次对输入的每一条指令进行分析和处理:
如果是M i j形式,则表示舰队排列发生了变化,你的程序要注意到这一点,但是不要输出任何信息;
如果是C i j形式,你的程序要输出一行,仅包含一个整数,表示在同一列上,第i号战舰与第j号战舰之间布置的战舰数目,如果第i号战舰与第j号战舰当前不在同一列上,则输出-1。
数据范围
N≤30000,T≤500000
原题链接:https://www.acwing.com/problem/content/240/
由于直接维护每对战舰之间的距离的时间复杂度非常大,所以我们考虑维护每个战舰到队头的距离,这样如果两只战舰在同一列上且i != j,那么我们就直接通过两个战舰各自到队头的距离相减得到答案,所以我们的查询函数可以这么写:
int Query(int a, int b)
{
if(a == b) return ;
if(issame(a, b)) return abs(d[a] - d[b]) - ; return -;
}
既然查询总是涉及子节点跟祖宗节点产生直接联系,那么我们可以考虑使用带权并查集来维护这个d[i],这个d[i]代表自己到父节点的距离,但是由于并查集的路径压缩,最终每个子节点的父节点都会变成他们的祖宗,也就是说这个d[i]就变成了子节点到祖宗的距离。

我们知道,对于祖宗来说,它到自己的距离是0,所以祖宗的d[i]是0,同时我们也能推出初始化的d[]数组也应该全部是0
那么在一棵树上的d[x]的更新跟路径压缩怎么去弄呢?
假设目前这颗树是长这样子的

那么路径压缩后应该长这样子

这里边发生的变化,其实就是3号节点接到了1号节点上,并且因为2号节点到1号节点的距离为1,然后3号节点到2号节点距离也是1,那么我们可以计算出3号节点到1号节点距离应该是d[2] + d[3] = 2。
达成这个目的的具体步骤也不难,就是先顺着3号节点用递归方式摸到2号节点再摸到1号节点,然后又从一号节点顺着那根线回来把距离都加到手

所以,我们的查找祖宗+路径压缩的代码就如下
int find(int x)
{
if(x == fa[x]) return x; //是祖宗就直接返回自己 int root = find(fa[x]); //找到根节点
d[x] += d[fa[x]]; //递归把距离一路加回来
fa[x] = root; //把子节点接到祖宗节点上
return root;
}
但是有个问题,两棵树合并时,也就是一个队插到另一个队的后面时,这个d怎么去更新才合适呢?

容易知道,当一个队插到另一个队的后面时,这个队的队头就排到了另一个队的队尾,那么我们就推算出这个队头到另一个队头的距离数值上等于另一个队的长度
因为涉及到队的长度,所以我们还要再引入一个信息,就是队的长度L
因为队的长度只有在两个不同的队合并时才会发生变化,所以这个L[]还是十分好维护的,就是两队长度相加即可
所以我们合并的时候,先更新祖宗d[x]再更新L[]就能达成任务了
void merge(int a, int b)
{
if(!issame(a, b)){
int root_a, root_b;
root_a = find(a);
root_b = find(b);
d[root_a] = l[root_b];
l[root_b] += l[root_a];
fa[root_a] = root_b;
}
}
查找、路径压缩以及合并,并查集的这些功能就水到渠成了
之后用就行
贴上AC代码
#include<iostream>
#include<algorithm>
using namespace std; const int Maxn = 3e4 + ;
int fa[Maxn];
int l[Maxn];
int d[Maxn]; int find(int x)
{
if(x == fa[x]) return x; //是祖宗就直接返回自己 int root = find(fa[x]); //找到根节点
d[x] += d[fa[x]]; //递归把距离一路加回来
fa[x] = root; //把子节点接到祖宗节点上
return root;
} bool issame(int a, int b)
{
return find(a) == find(b);
} void merge(int a, int b)
{
if(!issame(a, b)){
int root_a, root_b;
root_a = find(a);
root_b = find(b);
d[root_a] = l[root_b];
l[root_b] += l[root_a];
fa[root_a] = root_b;
}
} int Query(int a, int b)
{
if(a == b) return ;
if(issame(a, b)) return abs(d[a] - d[b]) - ; return -;
} int main()
{
for(int i=; i<Maxn ;i++){
fa[i] = i;
l[i] = ;
} int m;
cin>>m;
while(m--){
char op;
int i, j;
cin>>op>>i>>j;
if(op == 'M') merge(i, j);
else cout<<Query(i, j)<<endl;
} return ;
}
ACWing 238 银河英雄传说的更多相关文章
- NOI2002_ Galaxy银河英雄传说86
NOI2002_ Galaxy银河英雄传说86 公元五八○一年,地球居民迁移至金牛座α第二行星,:宇宙历七九九年,银河系的两大军事集团在巴米利恩星:杨威利擅长排兵布阵,巧妙运用各种战术屡次以少 ...
- P4847 银河英雄传说V2 题解(Splay)
题目链接 P4847 银河英雄传说V2 解题思路 我天哪!!!\(splay\)在\(rotate\)的时候先\(upd(y)\)再\(upd(x)\)!!以后不能再因为这个\(WA\)一晚上了!!! ...
- codevs1540 银河英雄传说
描述 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发战争.泰山压顶集 ...
- NOI2002 洛谷 P1196 银河英雄传说
神奇的并查集问题 题目描述 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦 创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩 ...
- NOI2002 银河英雄传说
P1196 银河英雄传说 367通过 1.1K提交 题目提供者该用户不存在 标签并查集NOI系列2001(或之前) 难度提高+/省选- 提交该题 讨论 题解 记录 最新讨论 莱因哈特什么鬼? 私人代码 ...
- codevs 1540 银河英雄传说
题目描述 Description 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米 ...
- 数据结构(并查集):COGS 260. [NOI2002] 银河英雄传说
260. [NOI2002] 银河英雄传说 ★★☆ 输入文件:galaxy.in 输出文件:galaxy.out 简单对比时间限制:5 s 内存限制:128 MB [问题描述] 公元五 ...
- CH4101 银河英雄传说
题意 4101 银河英雄传说 0x40「数据结构进阶」例题 描述 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七 ...
- codevs 1540 1540 银河英雄传说
1540 银河英雄传说 题目描述 Description 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银 ...
随机推荐
- 如何使用maven开启一个webapp项目
1.使用maven创建好一个webapp项目 2.pom.xml: 第一步:修改版本 <properties> <project.build.sourceEncoding>UT ...
- vue自定义分页组件---切图网
vue2.5自定义分页组件 Pagination.vue,可设置每页显示条数,带跳转框直接跳转到相应页面,亲测有用.目前很多框架自带有分页组件比如elementUI,不过在面对一个拿到PSD稿,然后重 ...
- 发布开源项目到Jcenter
前言 为了将阿里云短信开箱即用发布到Jcenter仓库,前前后后花费了1天半的时间,把端午节都搭进去了.终于今天收到了Jcenter的消息,自己发布的包被添加到了Jcenter仓库,也算给开源社区做了 ...
- CentOS7安装postgreSQL11
1.添加PostgreSQL Yum存储库 sudo yum install https://download.postgresql.org/pub/repos/yum/11/redhat/rhel- ...
- 洛谷P4526 【模板】自适应辛普森法2
P4526 [模板]自适应辛普森法2 洛谷传送门 题目描述 计算积分 保留至小数点后5位.若积分发散,请输出"orz". 输入格式 一行,包含一个实数,为a的值 输出格式 一行,积 ...
- js模拟form提交 导出数据
//创建模拟提交formfunction dataExport(option) { var form = $("<form method='get'></form>& ...
- Pikachu-XXE(xml外部实体注入漏洞)
XXE -"xml external entity injection"既"xml外部实体注入漏洞".概括一下就是"攻击者通过向服务器注入指定的xml ...
- HTML5音频(自定义mp3播放器源码)
audio对象 src兼容.ogg .wav .mp3 <audio controls src='data/imooc.wav'></audio> width autoplay ...
- Tensor--tensorflow的数据类型
在tensorflow2.0版本之前,1.x版本的tensorflow的基本数据类型有计算图(Computation Graph)和张量(Tensor)两种,但tensorflow2.0之后的版本取消 ...
- Linux环境搭建及基础操作
一.Linux环境搭建 1.安装虚拟机软件(VMWare,Parallel) 虚拟机的作用:将本来不是适合当前操作系统的分区虚拟化成适合当前操作系统的分区格式 2.新建虚拟机: 类似买了一台新的电脑, ...