概述
传送门
题解:
首先注意到换下来一个数之后,下一次的异或和就是这次换下来的数。
假设在 0 0 0号位置上有一个数是整个数列的xor和,则两个数列必须能够在重排之后完全相同才能有解。
注意到实际上我们每次是把0号位置和某一个位置上的数交换。
先把权值离散化一下。
每次我们可以把一个 a [ 0 ] a[0] a[0]上的数放到它该去的地方。
每个数向它该去的地方连边,对于每个连通块,显然是一个环,如果环中间包含 0 0 0号位置,我们可以直接用环长-1的代价来把这个环还原,否则我们需要环长的代价。
发现同样的数显然不用考虑位置已经对了的,只用考虑位置不对的。
直接用并查集维护一下连通性即可。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>
inline T get(){
char c;T num;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline int gi(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
cs int N=1e5+7;
int n,m;
int fa[N],vis[N];
int a[N],ta[N],b[N],tb[N];
inline int gf(int u){return u==fa[u]?u:(fa[u]=gf(fa[u]));}
signed main(){
#ifdef zxyoi
freopen("xor.in","r",stdin);
#endif
n=gi();
for(int re i=1;i<=n;++i)*a^=a[i]=ta[i]=gi();
for(int re i=1;i<=n;++i)*b^=b[i]=tb[i]=gi();
ta[0]=a[0];std::sort(ta,ta+n+1);
tb[0]=b[0];std::sort(tb,tb+n+1);
for(int re i=0;i<=n;++i)if(ta[i]!=tb[i])cout<<"-1",exit(0);
m=std::unique(ta,ta+n+1)-ta;
for(int re i=0;i<m;++i)fa[i]=i;
for(int re i=0;i<=n;++i){
a[i]=std::lower_bound(ta,ta+m,a[i])-ta;
b[i]=std::lower_bound(ta,ta+m,b[i])-ta;
}
int ans=0;
for(int re i=0;i<=n;++i)fa[gf(a[i])]=gf(b[i]),ans+=a[i]!=b[i]&&i;
for(int re i=0;i<m;++i)if(gf(i)^i)vis[fa[i]]=1;int t=gf(a[0]);
for(int re i=0;i<m;++i)if(gf(i)==i)ans+=vis[i]&&i!=t;
cout<<ans<<"n";
return 0;
}
最后
以上就是活力电话为你收集整理的【AGC016D】XOR Replace(推结论)(并查集)传送门题解:的全部内容,希望文章能够帮你解决【AGC016D】XOR Replace(推结论)(并查集)传送门题解:所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复