首页 > 其他分享 >[NOI2002]银河英雄传说

[NOI2002]银河英雄传说

时间:2023-08-21 16:11:05浏览次数:38  
标签:pre num int 英雄 银河 NOI2002 战舰 find dis

银河英雄传说TJ

题目背景

公元5801年,地球居民迁至金牛座第二行星,在那里发表银河联邦创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展。

宇宙历799年,银河系的两大军事集团在巴米利恩星域爆发战争。泰山压顶集团派宇宙舰队司令莱因哈特(B)率领十万余艘战舰出征,气吞山河集团点名将杨威利(A)组织麾下三万艘战舰迎敌。(废话)

题目描述

概括

两个阵营打仗,A方有30000艘战舰,开始每艘战舰独自占一行,A有时会给出合并指令,格式为M i j ,每次都将处在i号战舰所在行整体移到j号战舰所在行的最后。
有时B会发出查询指令,格式为C i j,如果i和j在同一列(pre[i]==pre[j])那么输出i和j的距离;如果不在同一列,就输出-1。

输入输出格式

输入格式

第一行一个整数T,1<=t<=5*105,表示一共有T条指令。
以下T行,每行一个指令。指令分为两种:

  1. M i j : 为杨威利的指令,表示合并
  2. C i j : 为莱因哈特的指令,表示查询

输出格式

依次对输入的指令进行分析和处理:
如果是M,不输出,把j这列的战舰直接移动到i这列的末尾(就是合并嘛)
如果是C,若i和j在同一列,输出i与j之间的战舰数目;若不在同一列,则输出-1

分析

对于这道题,首先不能被它的NOI身份和较长的描述吓到。

仔细观察,因为是并查集,所以可以把一艘战舰看成一个点,它所在的这排的第一艘船就可以看成根节点,这就具备了并查集的基本形状。

可以把问题分解成几个小问题:

  1. 如何存储前面的战舰,学过并查集的都知道用pre数组存

  2. 如何存储一个点到根节点的距离,执行C操作需要,我的想法是再开一个dis数组,直接记录每一个点到它的根节点的距离

  3. 如何实现M操作,朴素并查集的合并是直接合并根节点,不满足题目需要,所以可以用一个num数组,记录每一排的战舰数,每次合并时直接在dis[i]上加num[j],就可以对同一排内的战舰进行顺序区分

可以看到,每次dis[i]变化时,都是加上num[j],但pre[find(i)]可以直接连到pre[find(j)]上,这样就解决了M操作的问题
那么C操作其实就是求从i到j的节点数,因为有dis记录两点到同一点(根节点),就可以直接转化为求dis[i]-dis[j]的绝对值
所以问题就解决了,总共需要三个数组:pre,dis,num

Code

#include<bits/stdc++.h>
using namespace std;
int t;
char f;
int a,b;
int pre[30001],dis[30001],num[30001];
int find(int x){//带权并查集的路径压缩find
	if (pre[x]==x)return x;
	int sum=find(pre[x]);
	dis[x]+=dis[pre[x]];
	return pre[x]=sum;
}
int main(){
	scanf("%d",&t);
	for (int i=1;i<=30000;++i){
		pre[i]=i;
		num[i]=1;
	}
	for (int i=1;i<=t;++i){
		cin>>f;
		scanf("%d %d",&a,&b);
		int x=find(a),y=find(b);
		if (f=='M'){
			dis[x]=num[y];//x点到了末尾
			num[y]+=num[x];//b排要加上a排原数
			num[x]=0;//a排已经并到b排,所以没有战舰
			pre[x]=y;//真正的合并
		}
		else{
			if (x!=y){
				printf("-1\n");
			}
			else{
				printf("%d\n",abs(dis[a]-dis[b])-1);
			}
		}
	}
	return 0;
}

标签:pre,num,int,英雄,银河,NOI2002,战舰,find,dis
From: https://www.cnblogs.com/z10h09x11/p/17643682.html

相关文章

  • Linux笔记(银河麒麟V10)
    Linux下切换Python版本$whereispython$rm/usr/bin/python$ln-s/usr/bin/python3.6/usr/bin/python测试:$python--versionPython3.8.2安装Node.js-v18$curlhttps://nodejs.org/dist/v18.17.0/node-v18.17.0-linux-x64.tar.xz--outputnodejs18.tar.xz#......
  • KylinosV10银河麒麟高级服务器操作系统V10-安装telnet
    国产银河麒麟系统也是生产环境上经常遇到的(官网简介:银河麒麟高级服务器操作系统V10-国产操作系统、银河麒麟、中标麒麟、开放麒麟、星光麒麟——麒麟软件官方网站(kylinos.cn))这版系统分为服务器版和个人桌面版;其中服务器版命令估计是基于红帽体系;而桌面版命令估计是基于Ubunt......
  • 银河麒麟高级操作系统V10助力联通云建设打出组合拳
    联通云基于“双引擎基座+一云多芯”为不同行业场景提供可靠、高质量的应用上云服务。在核心代码进行了全面把控,定制多架构芯片应用适配模版,开发了计算、存储、网络、中间件等组件,全面适配自主化服务器和操作系统,提供云服务器、云硬盘、裸金属、负载均衡、虚拟私有云等多个IaaS和......
  • 银河麒麟等 Linux系统 安装 .net 5,net 6及更高版本的方法
    最近项目上用到银河麒麟的操作系统,需要搭建.net跨平台方案。一开始使用各种命令都安装不上,很多提示命令找不到,或者下载包时候网络无法下载。网上教程很多,但没有一个是成功的,多数使用apt-get等命令,都报错,提示命令未找到。于是开始手动安装。最终发现还是在Windows官网给出......
  • 中国电子云 银河麒麟v10yum源报错
    系统默认的yum源报错,访问默认源地址直接返回404,配置以下镜像源###KylinLinuxAdvancedServer10-osrepo###[ks10-adv-os]name=KylinLinuxAdvancedServer10-Osbaseurl=http://update.cs2c.com.cn:8080/NS/V10/V10SP1/os/adv/lic/base/$basearch/gpgcheck=0......
  • 【银河麒麟V10】【服务器】numa技术
    【银河麒麟V10】【服务器】numa技术桂安俊@kylinOS已于2022-10-1422:00:49修改2807收藏13分类专栏:#服务器操作系统版权服务器操作系统专栏收录该内容26篇文章42订阅订阅专栏目录1、numa介绍2、numa工具安装3、numa查看4、numa测试5、numa打开与关闭6、补充:服务器SMP......
  • 【银河麒麟】Python3.9的安装
    国产银河麒麟原装python3.5,版本较为落后,经过多次尝试+百度各种方法,现将安装python3.9的过程记录如下:1.安装依赖环境(打开终端)sudoaptupdatesudoapt-getinstallbuild-essentialzlib1g-devlibbz2-1.0libssl-devlibncurses5-devlibsqlite3-devlibreadline-devtk-de......
  • 银河麒麟V10 安装Nginx
    由于以下方式只能安装1.14.1版本安装Nginx:sudoyuminstallnginxNginx常用命令方法一:编辑/etc/rc.local,添加开机启动运行命令直接编辑/etc/rc.local文件,文件内容最底下添加启动命令:/usr/local/nginx/sbin/nginx1、启动Nginx服务器命令:去到sbin路径:cd/usr/local/nginx/sbin启动N......
  • 2023.8.1 英雄的力量
    题目要求返回所有的非空英雄组的力量之和,换言之,只要枚举到的所有组即可,不用管顺序如何。因此我们可以先对序列进行排序,一旦排序完成,那么max和min计算会变得非常简单。前i个数最大的一定是末端那个,最小的一定是起始那个。现在假设a,b,c,d,e五个数(已经排序)。如果现在令d为最大值......
  • 银河麒麟桌面安装java
    安装JavaJava是一种广泛应用于开发各种应用程序的编程语言。在Linux系统中,使用银河麒麟桌面环境,可以通过几个简单的步骤来安装Java。本文将介绍如何在银河麒麟桌面上安装Java,并附带代码示例。步骤一:检查是否已安装Java在开始安装Java之前,我们首先需要检查系统中是否已经安装了Ja......