传送门
题解:
首先注意到换下来一个数之后,下一次的异或和就是这次换下来的数。
假设在 0 0 0号位置上有一个数是整个数列的xor和,则两个数列必须能够在重排之后完全相同才能有解。
注意到实际上我们每次是把0号位置和某一个位置上的数交换。
先把权值离散化一下。
每次我们可以把一个 a [ 0 ] a[0] a[0]上的数放到它该去的地方。
每个数向它该去的地方连边,对于每个连通块,显然是一个环,如果环中间包含 0 0 0号位置,我们可以直接用环长-1的代价来把这个环还原,否则我们需要环长的代价。
发现同样的数显然不用考虑位置已经对了的,只用考虑位置不对的。
直接用并查集维护一下连通性即可。
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59#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内容请搜索靠谱客的其他文章。
发表评论 取消回复