首页 > 其他分享 >[AGC016D] XOR Replace 题解

[AGC016D] XOR Replace 题解

时间:2024-03-05 22:13:44浏览次数:19  
标签:XOR vis int 题解 dfs Replace ++ mp include

题意:

一个序列 \(a\),一次操作可以将某个位置变成整个序列的异或和。 求最少几步到达目标序列 \(b\)。

\(n \le 10^5\)

思路:

见到这种题,第一步要去尝试把操作转化。

稍微推一下可以发现,如果 \(\oplus_{i=1}^n a_i = s\),则相当于一个 \(n + 1\) 长序列,\(a_{n+1}=s\),每次可以交换 \(a_i\) 与 \(a_{n+1}\),求最少几次交换使得 \(a_1 \sim a_n\) 等于 \(b_1 \sim b_n\)。

无解说明又不包含的元素,这个可以直接判断。

考虑最终的答案,肯定是从 \(b_i \to x_1 \to x_2 \to \dots x_k \to a_i\) 的一条路径,所以我们不妨尝试将 \(b_i \to a_i\) 视作一条边。

所以我们要找的便是这张图中的一条从 \(s\) 出发的一条最短欧拉路径,如果这张图联通,因为我们现在是已经有解了,所以最短长度等于边数。

如果图不连通,则说明我们需要额外新增一下边使得图联通且存在欧拉路径,假设有 \(c\) 个联通分支,我们先弄 \(s\) 在的那个,然后是第二个,第三个以此类推,每次只需要多增加一条边即可。

假设我们连了 \(m\) 条边,则答案就是 \(m + e - 1\)。

为何是最小?首先,对于连通块内部的路径已经是最短的了,其次,将 \(c\) 个连通块变成一个也至少要 \(c - 1\) 条边,所以这个就是最优解。

点击查看代码
#include <iostream>
#include <vector>
#include <map> 
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + 5;

int n, a[N] = {0}, b[N] = {0};

map<int, int> mp;

vector<int> e[N];

bool vis[N] = {false};
void dfs(int x) {
	vis[x] = true;
	for (auto i: e[x])
		if (!vis[i])
			dfs(i);
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i], mp[a[i]]++, a[0] ^= a[i];
	for (int j = 1; j <= n; j++)
		cin >> b[j], mp[b[j]]--;
	mp[a[0]]++;
	for (auto i: mp)
		if (i.second < 0) {
			cout << -1;
			return 0;
		}
	int cur = 0;
	for (auto &i: mp)
		i.second = ++cur;
	a[0] = mp[a[0]];
	int ed = 0;
	for (int i = 1; i <= n; i++) {
		a[i] = mp[a[i]];
		b[i] = mp[b[i]];
		if (a[i] != b[i]) {
			e[b[i]].push_back(a[i]);
			e[a[i]].push_back(b[i]);
			ed++;
		}
	}
	
	int cnt = 0;
	for (int i = 1; i <= cur; i++)
		if (!vis[i] && (int)e[i].size() > 0)
			dfs(i), ++cnt;
	if ((int)e[a[0]].size() > 0)
		cnt--;
	cout << ed + cnt << endl;
	return 0;
} 

标签:XOR,vis,int,题解,dfs,Replace,++,mp,include
From: https://www.cnblogs.com/rlc202204/p/18055109

相关文章

  • 九省联考题解第一弹(1-8)
    2024九省联考题解样本数据16,24,14,10,20,30,12,14,40的中位数为?解:排序后为10,12,14,14,16,20,24,30,40,答案显然为16。椭圆\(\frac{x^2}{a^2}+y^2=1(a>1)\)的离心率为\(\frac{1}{2}\),求\(a\)。解:直接上椭圆基础公式。在题干中\(b=1\),离心率\(e=\frac{c}{a}=\frac{\sqrt{a^2-b^2}}{a}=\fr......
  • CF1925D Good Trip 题解
    Solution不好做的地方在于每一对朋友的友谊值是不同的,于是考虑将其统一为一个数。比较好想的就是将他们的初始友谊值提前计算,即对于每一次远足,设总情况为\(S=\frac{n\times(n-1)}{2}\),总的初始友谊值为\(w=\sum_{i=1}^{m}f_i\),假设友谊值不变,获得的期望友谊值为\(\frac{w}{......
  • ABC259Ex 题解
    Solution首先考虑暴力:枚举同种颜色的格子,假设两点为\((i,j),(x,y)\),那么从\((i,j)\)到\((x,y)\)的方案数即为\(C_{x-i+y-j}^{x-i}\)。考虑当前颜色有\(B\)个,枚举的时间复杂度为\(O(B^2)\)。考虑枚举每一种颜色,算出这种颜色到其他格子方案数,有递推方程:\(f_{i,j}=f_......
  • CF1800F 题解
    Solution考虑转化题目条件,因为要求字符串恰好有\(25\)个字符,所以考虑枚举没出现过的字符,令其为\(k\)。再令\(f_{i,p}\)表示第\(i\)个字符串\(p\)字符出现次数的奇偶,于是题目条件即为:\(f_{i,k}=f_{j,k}=0\)。\(f_{i,p}+f_{j,p}\bmod2=1\)。于是考虑用一个\(2^{26......
  • CF622F The Sum of the k-th Powers 题解
    原式为\(k+1\)次多项式,所以需要\(k+2\)个点确定。然后转化,前缀和。\[\begin{equation}n=k+2\\\end{equation}\]\[\begin{equation}f(x)=\sum\limits_{i=0}^{n}y_i\prod\limits_{j=0,j\nei}^{n}\frac{x-x_j}{x_i-x_j}\end{equation}\]\[\begin{equation}x_0=......
  • AT_abc331_f [ABC331F] Palindrome Query 题解
    分析线段树。每个节点维护两个值:$s[l\dotsr]$和$s[r\dotsl]$。判断字串是否是回文直接就是询问的答案维护出来的两个值是否相同。首先想到用线段树暴力维护。第一个值很显然是两个儿子的第一个值加起来,第二个值是反着加起来。得到很酷的代码:ilvoidup(intnow){ tr[now......
  • AT_abc287_g [ABC287G] Balance Update Query 题解
    分析一眼分块。用值域分块来维护。先把所有的值离散化,使得至于不大于$n+q$。统计一下每个值的数量,每个块包含值的数量,每个块的价值和。修改值的时候先把原来值的数量,块包含的数量,块的价值剪掉被修改值的贡献,然后在新的值上面更新。修改数量直接改数量的变化贡献即可。找前$x$......
  • P8844 [传智杯 #4 初赛] 小卡与落叶 题解
    分析乱搞题。$1\len,m\le10^5$的时候就可以考虑乱搞了。发现每次操作$1$都会把上一次的操作$1$覆盖掉,那么第$i$个询问时树的颜色情况就是由前$1$个操作$1$决定。也就是说这个询问的内容变成了:在$x$为根的子树中,深度不小于$x'$的节点数量。$x'$是该操作$1$......
  • AT_abc287_g [ABC287G] Balance Update Query 题解2
    分析权值线段树。给每个节点赋一个值$val$和$a_i=val$的$b_i$之和。修改$a_x$的时候先将$a_x$的出现次数在树上剪掉$b_x$,再在$y$上面加上;修改$b_x$的时候直接加上变化量$y-b_x$。由于我们是要取前$x$大的$a_i$之和,在询问的时候有限考虑右儿子,然后在是当前......
  • AT_abc335_f [ABC335F] Hop Sugoroku 题解
    比E简单。分析考虑暴力DP。定义状态函数$f_i$表示最后一个黑点为$i$时的方案数,有:$f_i=\sum\limits_{j=1}^{i-1}f_j[(i-j)\bmodval_j=0]$。不难发现在使用刷表法的时候,转移代码:for(reintj=1;i+val[i]*j<=n;++j)f[i+val[i]*j]=(f[i+val[i]*j]+f[i])%p;这玩意复杂......