题目
给定一个序列,前n-1个元素只能和第n个元素交换。问a序列至少交换多少次变成b序列。
题解
一种贪心的策略:如果a[i]=b[i],那么不交换i位置;离散化之后,a[i]连向b[i]。必然会连成一个个环。
显然,一个个环跑是最优的。
跑完一个环,再去跑另一个环。从一个环跳到另一个环,对答案的贡献为1.
最后一个环只需要跑到最后一个点就行了,无需跑最后一条边。
额外注意,a[n+1]可能独成一个大小为1的环。
必须拍,出多几个小数据。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#define N 100010
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
int i,j,k,l,n,m,ans;
int a[N],b[N],c[N],d[N];
int ca,cb,sa,sb,res;
int f[N];
bool bz[N];
int get(int x){
return f[x]==x?x:f[x]=get(f[x]);
}
void merge(int x,int y){
int gx=get(x),gy=get(y);
if(gx^gy)f[gy]=gx;
}
int main(){
scanf("%d",&n);
sa=sb=0;
fo(i,1,n)scanf("%d",&a[i]),c[i]=a[i],sa=sa^a[i];
fo(i,1,n)scanf("%d",&b[i]),d[i]=b[i],sb=sb^b[i];
a[n+1]=c[n+1]=sa;
b[n+1]=d[n+1]=sb;
sort(c+1,c+n+2);ca=unique(c+1,c+n+2)-c-1;
sort(d+1,d+n+2);cb=unique(d+1,d+n+2)-d-1;
if(ca^cb){printf("-1");return 0;}
fo(i,1,ca)if(c[i]^d[i]){printf("-1");return 0;}
fo(i,1,n+1)a[i]=lower_bound(c+1,c+ca+1,a[i])-c;
fo(i,1,n+1)b[i]=lower_bound(d+1,d+cb+1,b[i])-d;
fo(i,1,n+1)if(a[i]^b[i])f[a[i]]=a[i],f[b[i]]=b[i];
f[a[n+1]]=a[n+1],f[b[n+1]]=b[n+1];
fo(i,1,n+1)if(a[i]^b[i]){
if(i<=n)res++;
merge(a[i],b[i]);
}
fo(i,1,ca){
f[i]=get(f[i]);
if(f[i]==i)ans++;
}
ans+=res;
ans=max(ans-1,0);
printf("%d",ans);
return 0;
}