这道题目相当于是让我们把a,b对齐,即a中第i大的数与b中第i大的数下标相同
一看到交换次数,很容易让人想到归并排序
我的做法是这样的
就样例而言:
a:1 3 4 2
b:1 7 2 4
读进来之后先处理a,b 把a,b按大小离散成1..n
离散之后
a:1 3 4 2
b:1 4 2 3
那么我们现在的问题就变成了,求a转化为b所用的次数
但是仍然很麻烦,所以要进一步离散 - -!
我们不难看出,在a数组中,1的目的地是1。2的目的地是3。3的目的地是4.4的目的地是2
那么我们可以另开一个数组,p[i]记录a[i]的目的地,即p={1,4,2,3}
当a的元素全都到达目的地之后,p数组就是{1,2,3,4}
所以答案就是使P数组变成1..n所需要的移动次数,也就是p的逆序对个数
如何求逆序对? http://www.cnblogs.com/FuTaimeng/p/5652994.html
代码:
#include<iostream> #include<algorithm> #define Size 100005 using namespace std; int n; int a[Size],b[Size]; struct T{ int num,p; }temp[Size]; int f[Size],place[Size]; int cc[Size]; int ans=0; bool ff(T x,T y){return x.num<y.num;} void lisan(T x[],int y[]){ sort(x+1,x+1+n,ff); for(int i=1;i<=n;i++){ y[x[i].p]=i; } } void he(int st,int end,int mid){ int l=st,r=mid+1; for(int i=st;i<=end;i++){ if(l<=mid&&(r>end||f[l]<=f[r])){ cc[i]=f[l]; l++; } else{ cc[i]=f[r]; r++; ans+=mid-l+1; ans%=99999997; } } for(int i=st;i<=end;i++)f[i]=cc[i]; } void my_msort(int l,int r){ if(l<r){ int mid=(l+r)/2; my_msort(l,mid); my_msort(mid+1,r); he(l,r,mid); } } int main(){ cin>>n; for(int i=1;i<=n;i++)cin>>temp[i].num,temp[i].p=i; lisan(temp,a); for(int i=1;i<=n;i++)cin>>temp[i].num,temp[i].p=i; lisan(temp,b); for(int i=1;i<=n;i++)place[b[i]]=i; for(int i=1;i<=n;i++){ f[i]=place[a[i]]; } my_msort(1,n); cout<<ans<<endl; }