分析
我们根据提示发现,其实序列有n+1个元素,多出来那一个就是异或和
那么问题转换为怎么将序列经过抽出塞入变成目标序列
然后我们将初始序列和目标序列中同位不同的连边,然后看一下有多少联通块即可
但是如果异或和没有用到,也要+1,因为需要先把异或和放进去从而取出来一个数
答案等于联通块大小+联通块个数-1
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include <map> #include <memory.h> using namespace std; const int N=1e5+10; map<int,int> p; vector<int> l[N]; int a[N],b[N],c[N],d[N]; int n,lsh,ans; bool vis[N]; void Dfs(int u) { vis[u]=1; int sz=l[u].size(); for (int i=0;i<sz;i++) if (!vis[l[u][i]])Dfs(l[u][i]); } int main() { freopen("duliu.in","r",stdin); freopen("duliu.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]),a[n+1]^=a[i],!p[a[i]]?p[a[i]]=++lsh:i=i; if (!p[a[n+1]]) p[a[n+1]]=++lsh; for (int i=1;i<=n;i++) scanf("%d",&b[i]),b[n+1]^=b[i],!p[b[i]]?p[b[i]]=++lsh:i=i; if (!p[b[n+1]]) p[b[n+1]]=++lsh; memcpy(c,a,sizeof a);memcpy(d,b,sizeof b); sort(a+1,a+n+2);sort(b+1,b+n+2); for (int i=1;i<=n;i++) if (a[i]!=b[i]) { printf("-1"); return 0; } for (int i=1;i<=n;i++) if (c[i]!=d[i]) l[p[c[i]]].push_back(p[d[i]]),ans++; if (c[n+1]!=d[n+1]) l[p[c[n+1]]].push_back(p[d[n+1]]); for (int i=1;i<lsh;i++) if (l[i].size()&&!vis[i]) Dfs(i),ans++; if (!vis[lsh]) ans++; ans--; printf("%d",ans); }