zoukankan      html  css  js  c++  java
  • [NOI2002] 银河英雄传说 (带权并查集)

    题目描述

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

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

    杨威利擅长排兵布阵,巧妙运用各种战术屡次以少胜多,难免恣生骄气。在这次决战中,他将巴米利恩星域战场划分成 30000 列,每列依次编号为 1, 2, …,30000 。之后,他把自己的战舰也依次编号为 1, 2, …, 30000,让第 i 号战舰处于第 i 列 (i = 1, 2, …, 30000),形成“一字长蛇阵”,诱敌深入。这是初始阵形。当进犯之敌到达时,杨威利会多次发布合并指令,将大部分战舰集中在某几列上,实施密集攻击。合并指令为 Mi,j​ ,含义为第i号战舰所在的整个战舰队列,作为一个整体(头在前尾在后)接至第j号战舰所在的战舰队列的尾部。显然战舰队列是由处于同一列的一个或多个战舰组成的。合并指令的执行结果会使队列增大。

    然而,老谋深算的莱因哈特早已在战略上取得了主动。在交战中,他可以通过庞大的情报网络随时监听杨威利的舰队调动指令。

    在杨威利发布指令调动舰队的同时,莱因哈特为了及时了解当前杨威利的战舰分布情况,也会发出一些询问指令: Ci,j​ 。该指令意思是,询问电脑,杨威利的第 i 号战舰与第 j 号战舰当前是否在同一列中,如果在同一列中,那么它们之间布置有多少战舰。

    作为一个资深的高级程序设计员,你被要求编写程序分析杨威利的指令,以及回答莱因哈特的询问。

    最终的决战已经展开,银河的历史又翻过了一页……

    输入输出格式

    输入格式:

    第一行有一个整数 T(1≤T≤500,000) ,表示总共有 T 条指令。

    以下有 T 行,每行有一条指令。指令有两种格式:

    1. Mi,j​ : i 和 j 是两个整数 (1≤i,j≤30000) ,表示指令涉及的战舰编号。该指令是莱因哈特窃听到的杨威利发布的舰队调动指令,并且保证第 i 号战舰与第 j 号战舰不在同一列。

    2. Ci,j​ : i 和 j 是两个整数 (1≤i,j≤30000) ,表示指令涉及的战舰编号。该指令是莱因哈特发布的询问指令。

    输出格式:

    依次对输入的每一条指令进行分析和处理:

    如果是杨威利发布的舰队调动指令,则表示舰队排列发生了变化,你的程序要注意到这一点,但是不要输出任何信息;

    如果是莱因哈特发布的询问指令,你的程序要输出一行,仅包含一个整数,表示在同一列上,第 i 号战舰与第 j 号战舰之间布置的战舰数目。如果第 i 号战舰与第 j 号战舰当前不在同一列上,则输出 -1 。

    输入输出样例

    输入样例#1:

    4
    M 2 3
    C 1 2
    M 2 4
    C 4 2

    输出样例#1:

    -1
    1

    说明

    【样例说明】

    战舰位置图:表格中阿拉伯数字表示战舰编号

    题解

    带权并查集裸题

    我只需要在普通的并查集中加入一个数组dep[i],代表i到i所在的这一列的距离,cnt[i]表示以i为队首(只有队首才有值)的队伍中元素的个数

    对于一个M操作,将i号战舰的队首接到j号战舰队列的队尾,(运用路径压缩的思想)即把find(i)接到find(j)上,这样操作后,cnt[j]就会增加cnt[i]个,而dep[i]就会增加cnt[j]个,至于原i队伍中其他元素,我们在find函数中处理

    而对于每一个C操作,我们只需判断i与j是否在同一个并查集中,即find(i)是否等于find(j),如果不相等则输出-1,相等则输出两队首之差的绝对值-1

    #include<bits/stdc++.h>
    #define in(i) (i=read())
    using namespace std;
    int read()
    {
    	int ans=0,f=1;
    	char i=getchar();
    	while(i<'0' || i>'9'){
    		if(i=='-') f=-1;
    		i=getchar();
    	}
    	while(i>='0' && i<='9'){
    		ans=(ans<<1)+(ans<<3)+i-'0';
    		i=getchar();
    	}
    	return ans*f;
    }
    int T;
    int fa[30010];
    int dep[30010],cnt[30010];
    int find(int x) {
    	if(fa[x]==x) return x;
    	int root=find(fa[x]);
    	dep[x]+=dep[fa[x]];
    	return fa[x]=root;
    }
    int main()
    {
    	in(T);
    	for(int i=1;i<=30000;i++) {
    		fa[i]=i;
    		dep[i]=0;cnt[i]=1;	
    	}
    	for(int t=1;t<=T;t++) {
    		char opt;int x,y;
    		cin>>opt;
    		in(x);in(y);
    		int fx=find(x),fy=find(y);
    		if(opt=='M') {
    			fa[fx]=fy;
    			dep[fx]+=cnt[fy];
    			cnt[fy]+=cnt[fx];
    			cnt[fx]=0;
    		}
    		else {
    			if(fx!=fy) cout<<-1<<endl;
    			else cout<<abs(dep[x]-dep[y])-1<<endl;
    		}
    	}
    }
    
  • 相关阅读:
    Spring Boot中通过CORS解决跨域问题
    使用aop注解实现表单防重复提交功能
    Springboot分别使用乐观锁和分布式锁(基于redisson)完成高并发防超卖
    关于日期格式yyyy-MM-dd和YYYY-MM-dd
    基于Java8的日期时间工具类DateTimeFormatter
    Springboot 配置 ssl 实现HTTPS 请求 & Tomcat配置SSL支持https请求
    springboot+layui实现PC端用户的增删改查 & 整合mui实现app端的自动登录和用户的上拉加载 & HBuilder打包app并在手机端下载安装
    Springboot的日志管理&Springboot整合Junit测试&Springboot中AOP的使用
    Springboot实体类转JSON报错Could not find acceptable representation & 设置访问项目根路径的默认欢迎页面
    SpringMVC 使用@ResponseBody返回json 中文乱码与返回实体类报错
  • 原文地址:https://www.cnblogs.com/real-l/p/9189002.html
Copyright © 2011-2022 走看看