[AGC016D] XOR Replace 题解

[AGC016D] XOR Replace

来自 @qzmoot 同一机房的同学的题解。

模拟赛用不同的思路场切了。

题面大意:一个序列,一次操作可以将某个位置变成整个序列的异或和。 问最少几步到达目标序列。

来自梦熊的题面:

有一个长度为 n n n 的序列 a a a,有以下函数:

void update(int u){
	int w=0;
	for(int i=1;i<=n;i++) w^=a[i];
	a[u]=w;
}

你可以执行这个函数若干次,其中参数 u u u 由你指定,请问将序列 a a a 修改为序列 b b b 的最小调用次数是多少。

分析:

操作逻辑简化

我们先要知道这个操作在干什么。

如果你指定一个 u u u,使 w = a u w = a_u w=au a u = ⊕ i = 1 n a i a_u = \oplus_{i = 1}^n a_i au=i=1nai

那么当你再指定一个 u ′ u^{\prime} u 时, a u ′ = ⊕ i = 1 n a i = w a_{u^{\prime}} = \oplus_{i = 1}^n a_i = w au=i=1nai=w

这是由于异或具有自反性。

那么,这个操作就相当于你有一个初始为 a a a 的序列,同时手里还纂着一个 ⊕ i = 1 n a i \oplus_{i = 1}^n a_i i=1nai,你每次可将手中的数和序列中的数交换,直到序列 a a a 变成序列 b b b

合法情况判断

接下来判断的是怎样才是合法的局面。

根据上面的分析,容易发现这个序列 a a a 有两种情况:

  1. 序列 a a a 和序列 b b b 的数种类相同,且每种种类的数的个数相同。
  2. 序列 a a a 和序列 b b b 的数种类只有一种不同,该种类数的个数是 1 1 1,且该数为初始的 ⊕ i = 1 n a i \oplus_{i = 1}^n a_i i=1nai
最小操作数

接下来是最小操作数的分析。

我们的操作肯定是取出一个数,直接放进与 b b b 对应的位置。

因为只有合法局面(序列中的数一定是一一对应的)才会计算最小操作数,所以这样做一定是最优的。

并且 a a a b b b 已经匹配上的位置可以不用考虑。

那么,你会发现我们的拿取操作形成了一个环或链。

因此,我们可以将 a a a b b b 中的对应位置的数连边。

其必然形成若干简单环和链,如图:

img

img

对于链,其中必定有 ⊕ i = 1 n a i \oplus_{i = 1}^n a_i i=1nai,这时最小操作数为链的边数个数

对于环,其中必定没有 ⊕ i = 1 n a i \oplus_{i = 1}^n a_i i=1nai,这时我们会先将 ⊕ i = 1 n a i \oplus_{i = 1}^n a_i i=1nai 放到任意一个位置,最后将所有环中数字位置调整完后取出来,最小操作数为环的边数 + 1

用并查集统计答案就可以过了。

最后由于 a i , b i < 2 30 a_i,b_i < 2^{30} ai,bi<230,所以用并查集计算答案之前需要离散化。

这种方法好像不需要判孤立点(大概吧,本人没有仔细研究)。

AC-code:

#include<bits/stdc++.h>
using namespace std;
#define int long long
int rd() {
	int x = 0, w = 1;
	char ch = 0;
	while (ch < '0' || ch > '9') {
		if (ch == '-') w = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = x * 10 + (ch - '0');
		ch = getchar();
	}
	return x * w;
}
void wt(int x) {
	static int sta[35];
	int f = 1;
	if(x < 0) f = -1,x *= f;
	int top = 0;
	do {
		sta[top++] = x % 10, x /= 10;
	} while (x);
	if(f == -1) putchar('-');
	while (top) putchar(sta[--top] + 48);
}
signed main() {
	int n = rd(),top = 0;
	vector<int> a(n),b(n),c(n * 2),s(n * 2),siz(n * 2),t(n * 2);
	vector<bool> bok(n * 2),ext(n * 2);
	vector<int> in(n * 2);
	for(int i = 0;i<n;i++) a[i] = rd();
	for(int i = 0;i<n;i++) b[i] = rd();
	for(int i = 0;i<n;i++) c[top++] = a[i],c[top++] = b[i];
	int w = 0;
	for(int i = 0;i<n;i++) w ^= a[i];
	c.emplace_back(w);	
	sort(c.begin(),c.end());
	top = unique(c.begin(),c.end()) - c.begin() - 1;
	for(int i = 0;i<n;i++) 
		a[i] = lower_bound(c.begin(),c.begin() + top + 1,a[i]) - c.begin(),
		b[i] = lower_bound(c.begin(),c.begin() + top + 1,b[i]) - c.begin();
	w = lower_bound(c.begin(),c.begin() + top + 1,w) - c.begin();
	for(int i = 0;i<n;i++) t[a[i]]++;
	t[w]++;
	for(int i = 0;i<n;i++) {
		t[b[i]]--;
		if(t[b[i]] < 0) {puts("-1");return 0;}
	}
	bool flag = false;
	for(int i = 0;i<n;i++) 
		if(a[i] != b[i]) {flag = true;break;}
	if(!flag) {wt(0);return 0;}
	for(int i = 0;i<n * 2;i++) {s[i] = i;ext[i] = 0;siz[i] = 0;bok[i] = 0;}
	for(int i = 0;i<n;i++) {
		if(a[i] == b[i]) continue;
		bok[a[i]] = bok[b[i]] = true;
		siz[b[i]]++;
		if(w == b[i]) ext[b[i]] = true; 
	}
	auto find = [&](auto self,int x) -> int {
		if(s[x] ^ x) 
			s[x] = self(self,s[x]);
		return s[x];
	};
	for(int i = 0;i<n;i++) {
		if(a[i] == b[i]) continue;
		int fa = find(find,a[i]),fb = find(find,b[i]);
		if(fa != fb) {
			s[fa] = fb;
			siz[fb] += siz[fa];
			ext[fb] = ext[fb] | ext[fa];
		}
	}
	int ans = 0;
	for(int i = 0;i<n * 2;i++) {
		if(bok[i] && find(find,i) == i) {
			if(ext[find(find,i)]) ans += siz[find(find,i)];
			else ans += siz[find(find,i)] + 1;
		}
	}
	wt(ans);
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/914886.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu 24.04运行chattts时cuda安装错误原因分析

使用ubuntu 24.04&#xff0c;按照2noise/ChatTTS官方流程安装依赖时报错。ChatTTShttps://github.com/2noise/ChatTTS 这是因为cuda版本不对&#xff0c;ChatTTS目前的版本&#xff0c;要求支持cuda 12.4及以上&#xff0c;但是如果nvidia显卡驱动版本较老&#xff0c;无法支…

力扣-Hot100-技巧【算法学习day.31】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&am…

Spark的容错机制

1&#xff0c;Spark如何保障数据的安全 1、RDD容错机制&#xff1a;persist持久化机制 1&#xff09;cache算子 - 功能&#xff1a;将RDD缓存在内存中 - 语法&#xff1a;cache() - 本质&#xff1a;底层调用的还是persist&#xff08;StorageLevel.MEMORY_ONLY&#xff09;&…

【漏洞分析】Fastjson最新版本RCE漏洞

01漏洞编号 CVE-2022-25845CNVD-2022-40233CNNVD-202206-1037二、Fastjson知多少 万恶之源AutoType Fastjson的主要功能是将Java Bean序列化为JSON字符串&#xff0c;这样得到的字符串就可以通过数据库等方式进行持久化了。 但是&#xff0c;Fastjson在序列化及反序列化的过…

推荐一款电脑清理和加速工具:Wise Care 365 Pro

Wise Care 365 Pro是一款可以清理注册表和磁盘垃圾文件&#xff0c;保护个人隐私记录&#xff0c;提高电脑使用安全的软件&#xff0c;是优化系统、提高Windows系统运行速度最好的选择!实时保护注册表不被其他程序未经许可地秘密修改。例如阻止程序更改您的浏览器主页&#xff…

微信小程序,点击bindtap事件后,没有跳转到详情页,有可能是app.json中没有正确配置页面路径

文章目录 1、index.wxml2、index.js检查点1. 确保目标页面存在2. 确保页面路径配置正确3. 检查页面接收参数productDetail.jsproductDetail.wxmlproductDetail.wxss 总结 1、index.wxml <!-- 商品搜索结果卡片容器 --><view class"search-result"><bl…

合理的止盈可以在盈利的时候保证期望的收益

吸取他人经验是每位交易者成长的必经之路。无论是新手还是老手&#xff0c;面对瞬息万变的市场&#xff0c;都需要不断学习。今天&#xff0c;我们特邀Eagle Trader的优秀交易员胡浩先生&#xff0c;分享他在交易中的实战经验与学习心得。在短暂的采访中&#xff0c;胡浩先生似…

ISAAC SIM踩坑记录--ROS2相机影像发布

其实这个例子官方和大佬NVIDIA Omniverse和Isaac Sim笔记5&#xff1a;Isaac Sim的ROS接口与相机影像、位姿真值发布/保存都已经有详细介绍了&#xff0c;但是都是基于ROS的&#xff0c;现在最新的已经是ROS2&#xff0c;这里把不同的地方简单记录一下。 搭建一个简单的场景&a…

【thm】 Investigating Windows

0x00 rdp连接目标机器 apt install rdesktop 我们直接在kali里面安装这个&#xff0c;然后去连接 rdesktop 10.10.187.161 然后直接输入用户名密码就可。 0x01 hacker的任务 查看系统的信息&#xff0c;我们直接在命令行中输入systeminfo就可以直接查看。 然后我们输入 Get…

Python爬虫知识体系-----requests-----持续更新

数据科学、数据分析、人工智能必备知识汇总-----Python爬虫-----持续更新&#xff1a;https://blog.csdn.net/grd_java/article/details/140574349 文章目录 一、安装和基本使用二、get请求三、post请求四、代理 一、安装和基本使用 和解析库urllib几乎一摸一样&#xff0c;但是…

Netty篇(入门编程)

目录 一、Hello World 1. 目标 2. 服务器端 3. 客户端 4. 流程梳理 &#x1f4a1; 提示 5. 运行结果截图 二、Netty执行流程 1. 流程分析 2. 代码案例 2.1. 引入依赖 2.2. 服务端 服务端 服务端处理器 2.3. 客户端 客户端 客户端处理器 2.4. 代码截图 一、Hel…

酯化反应干催化剂树脂

油酸酯和丙三醇的合成反应&#xff1a; 油酸酯和丙三醇的合成反应是一个酯化反应&#xff1a;酯化反应的基本原理和条件&#xff0c; 在这个反应中&#xff0c;丙三醇&#xff08;甘油&#xff09;和油酸反应生成三酸甘油酯&#xff08;油酸酯&#xff09;和水。这种反应通常在…

Java 值传递详解

目录 形参&实参 值传递&引用传递 为什么 Java 只有值传递&#xff1f; 案例 1&#xff1a;传递基本类型参数 案例 2&#xff1a;传递引用类型参数 1 案例 3&#xff1a;传递引用类型参数 2 引用传递是怎么样的&#xff1f; 为什么 Java 不引入引用传递呢&#x…

Hadoop(环境搭建篇)

这里我用的是ubnatu22.4的系统&#xff0c;请大家严格按照这个系统来安装 一、网络设置 1、打开虚拟机的编辑&#xff0c;并选择虚拟网络编辑器 2、点击更改设置 3、更改IP 二、更改主机名 1、打开终端 2、输入以下命令 hostnamectl set-hostname master 3、然后关闭终端在…

深入浅出研究AI协同办公领域发展和趋势

协同办公&#xff0c;又称OA&#xff0c;是指企业内部或外部各类人员之间利用信息技术来进行协作工作的一种形式。这种协作工作既可以由直接员工进行&#xff0c;也可以来自外部的咨询机构、合作伙伴或联营企业。协同办公的优势在于可以对资源进行有效管理和配置&#xff0c;各…

C语言数据结构与算法--简单实现栈的出栈与入栈

&#xff08;一&#xff09;栈的基本概念 栈(Stack)是限定仅在表尾进行插入和删除操作的线性表&#xff0c;如铁路调度。如下 图&#xff1a; &#xff08;二&#xff09;栈的的表现形式 栈有两种表示形式&#xff1a;栈的表示和实现、栈的 链式表示。 1&#xff0e;栈的表示…

数据分析-46-时间序列显示之如何精准可视化多个时间序列数据

文章目录 1 可视化1.1 可视化的重要性1.2 数据加载探索2 可视化单个时间序列2.1 无连接线的散点图2.2 带连接线的散点图2.3 无点的线图2.4 填充区域的线图3 可视化多个时间序列3.1 无连接的散点图(差的设计)3.2 带连接的散点图(好的设计)3.3 直接标注的曲线(优的设计)4 参考附录…

ubuntu24.04播放语音视频

直接打开ubuntu自带的video播放.mp4文件&#xff0c;弹窗报错如下&#xff1a; 播放此影片需要插件 MPEG-4 AAC 编码器安装方式&#xff1a; sudo apt install gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly sudo apt install ffmpeg验证AA…

python第七次作业

01.设计一个函数&#xff0c;可以传入一个或多个单词的字符串&#xff0c;并返回该字符串&#xff0c;但所有五个或更多字母的单词都前后颠倒 a input("输入:") print(a) #将一句话以空格为分界拆分为单个单词 b a.split(" ") ls_1 [] ls_2 []for i i…

精挑细选的五款GIS工具箱,你需要了解的优缺点

本文将为大家介绍五款功能各异的GIS工具箱&#xff0c;包括GISBox、QGIS、MapTiler、Saga GIS和Whitebox GAT。每款工具箱都有其独特的功能和应用场景&#xff0c;能够满足不同类型的GIS任务需求。无论是数据处理、空间分析、影像处理还是可视化需求&#xff0c;这些工具都能为…