题意

题目链接

给出两个长度为\(n\)的数组\(a, b\)

每次可以将\(a\)中的某个数替换为所有数\(xor\)之和。

若\(a\)数组可以转换为\(b\)数组,输出最少操作次数

否则输出\(-1\)

Sol

一般那看到这种\(N \leqslant 10^5\)而且不可做的题肯定是先找结论啦

不难看出,我们把所有数\(xor\)起来的数替换掉之后再次\(xor\),得到的一定是被替换掉的数。

实际上,我们可以把xor出来的数放到一个新的位置\(N+1\),这样每次操作就变成了交换第\(N+1\)个位置的数和任意一个位置\(x\)的数

总的问题就变成了

给出两个长度为\(N+1\)的数组\(a, b\),每次可以在\(a\)中交换\(\forall i \in [1, n]\)位置和\(N+1\)位置的数,问最少交换几次变为\(b\)数组

首先把\(-1\)的情况判掉,很显然,把两个数组排序后,若存在一个位置不相同,则一定无解

否则一定有解。

到这里我就不会了。。。。

官方题解非常神仙。

对于\(i\)位置,若\(a_i \not = b_i\),则向\(a_i\)到\(b_i\)连一条边

最终答案 = 总边数 + 联通块数 - 1

想一想为什么,对于联通块内的点,假设其大小为\(x\),我们一定可以通过\(x-1\)次操作把他们对应的\(a\)和\(b\)变的相同

对于不同联通块之间,我们还需要一步操作使得第\(N+1\)个位置的数在两个联通块之间转化(第一个除外)

对于第\(N+1\)个位置需要单独考虑:如果它已经在联通块里则不需要考虑,否则把它看做单独联通块

否则

2
1 3
3 1

可以用并查集维护联通块个数

#include<bits/stdc++.h>
const int MAXN = 4e5 + 10;
using namespace std;
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int N;
int a[MAXN], b[MAXN], ta[MAXN], tb[MAXN], sa, sb, tot = 0, date[MAXN], fa[MAXN];
map<int, bool> ti;
int find(int x) {
return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);
}
int unionn(int x, int y) {
fa[x] = y;
}
int main() {
N = read();
for(int i = 1; i <= N; i++) a[i] = read(), sa ^= a[i]; a[N + 1] = sa;
for(int i = 1; i <= N; i++) b[i] = read(), sb ^= b[i]; b[N + 1] = sb;
N++;
memcpy(ta, a, sizeof(a)); memcpy(tb, b, sizeof(b));
sort(ta + 1, ta + N + 1); sort(tb + 1, tb + N + 1);
for(int i = 1; i <= N - 1; i++) if(ta[i] != tb[i]) return puts("-1"), 0; int ans = 0, num = 0;
for(int i = 1; i <= N; i++)
if(a[i] != b[i] || (i == N)) {
date[++num] = a[i]; date[++num] = b[i];
if(i < N)ans++;//最后一块单独考虑
}
if(ans == 0) return puts("0"), 0; sort(date + 1, date + num + 1);
num = unique(date + 1, date + num + 1) - date - 1;
for(int i = 1; i <= num; i++) fa[i] = i;
for(int i = 1; i <= N; i++)
if(a[i] != b[i]) {
a[i] = lower_bound(date + 1, date + num + 1, a[i]) - date,
b[i] = lower_bound(date + 1, date + num + 1, b[i]) - date;
if(!ti[a[i]]) ti[a[i]] = 1;
if(!ti[b[i]]) ti[b[i]] = 1;
unionn(find(a[i]), find(b[i]));
} for(int i = 1; i <= num; i++)
if(fa[i] == i) ans++;
printf("%d", ans - 1); return 0;
}

最新文章

  1. Java基础之类Class使用
  2. Java中单例
  3. 深入理解javascript原型和闭包(14)——从【自由变量】到【作用域链】
  4. [vijos P1040] 高精度乘法
  5. 《PHP开发APP接口》笔记
  6. Matlab里面的SVM
  7. 技术那么多,你想看看JSON Schema的测试吗?
  8. Inno Setup 创建站点,创建虚拟目录
  9. haproxy path_end不能忽略
  10. 【LeetCode练习题】Partition List
  11. 14.4.3.5 Configuring InnoDB Buffer Pool Flushing 配置InnoDB Buffer Pool 刷新:
  12. onethink和phpwind共享
  13. 小白也能看懂的插件化DroidPlugin原理(二)-- 反射机制和Hook入门
  14. Java面试准备之集合框架
  15. eclipse中导入jsp等工程使用过程中常遇问题
  16. Android双击Home键返回桌面
  17. Nginx(二)------nginx.conf 配置文件
  18. Day3-1 函数
  19. Service(服务)
  20. PAT A1021 Deepest Root (25 分)——图的BFS,DFS

热门文章

  1. HDOJ.1029 Ignatius and the Princess IV(map)
  2. [学习笔记]Segment Tree Beats!九老师线段树
  3. ACE线程管理机制-线程的创建与管理
  4. jq 正则
  5. Python os.walk文件遍历
  6. POJ 2823 Sliding Window ST RMQ
  7. 超酷算法-BK树
  8. bzoj 2200: [Usaco2011 Jan]道路和航线——拓扑+dijkstra
  9. 【51NOD-5】1293 球与切换器
  10. 【BZOJ】1014 [JSOI2008]火星人prefix