题解:AT_agc016_d [AGC016D] XOR Replace
Lovely_Rabbit · · 题解
本文作者 @tanglb,是校内模拟赛 T2 题解,经过作者同意后代为交到原题 AT_agc016_d 题解区。有修改。
先模拟一下这个操作:
设
由此发现,每次对
现在我们保证有解,如何确定最小步数?
贪心的想,每一次交换都应尽量匹配一组
上面不断交换的过程中,
建出的图可能不连通,当我们要从一个连通块跳到另一个连通块时,可以通过加一条边来实现。例如从
根据上文结论,最小操作次数等价于边数,设连通块数为
这里放一个并查集做法的代码。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[200005];
int b[200005];
int ans;
map<int,int>mp;
map<int,int>fa;
int find(int x){
if(fa[x]==0)return fa[x]=x;
return(x==fa[x]?x:fa[x]=find(fa[x]));
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(),cout.tie();
int n;
cin>>n;
int flc=0;
for(int i=1;i<=n;i++)
cin>>a[i],mp[a[i]]++,a[n+1]^=a[i];
for(int i=1;i<=n;i++)
cin>>b[i],mp[b[i]]--;
mp[a[n+1]]++;
int sum=0;
for(auto i:mp)
if(i.second)sum++;
if(sum!=1){
puts("-1");
return 0;
}
for(int i=1;i<=n;i++)
if(a[i]==b[i])flc--;
for(int i=1;i<=n+1;i++)a[i]++;
for(int i=1;i<=n;i++)b[i]++;
for(int i=1;i<=n;i++)
fa[find(a[i])]=find(b[i]);
sum=0;
mp.clear();
for(int i=1;i<=n;i++){
if(a[i]==b[i])continue;
if(find(b[i])==b[i]&&!mp[b[i]])sum++,mp[b[i]]=1;
}
for(int i=1;i<=n;i++)
if(b[i]==a[n+1]&&a[i]!=b[i]){
sum--;
break;
}
cout<<n+sum+flc;
return 0;
}
// 关注 fish_love_cat (uid=754021) 谢谢喵