题目大意:给你两个有序数组a,b并定义a,b间的距离为∑(ai-bi)^2,要求交换a或者b中的某些元素的位置使得a,b间距离最小。
由于∑(ai-bi)^2=∑(ai^2)+∑(bi^2)-2*∑aibi;而由于题目给定了ai,bi的值,所以∑(ai^2)、∑(bi^2)是定值,要求原式最小就需要∑aibi最大。
而根据排序不等式原理,∑aibi最大值是ai,bi的顺序和。
所以先把ai按照高度排好序,bi也按照高度排好序。题目所求就是排好序的ai和bi编号要求1~6一一对应时的排序次数。
用一个数组记录ai,bi编号间的对应关系,再求逆序对个数即可。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstdlib>
#include<cstring>
#define mo 99999997
#define maxn 100010
using namespace std;
typedef long long LL;
int n;
struct data
{
int v,id;
}A[maxn],B[maxn];
bool cmp(data a,data b)
{
return a.v<b.v;
}
int x[maxn],t[maxn];
LL merge_sort(int x,int y,int *a)
{
if(x>=y)return 0;
int m=x+y>>1;
LL t1=merge_sort(x,m,a);
LL t2=merge_sort(m+1,y,a);
LL t3=0;
int i=x,j=m+1,k=x;
while(i<=m && j<=y)
{
if(a[i]>a[j])
{
t[k++]=a[j++];
t3=(t3%mo+(m-i+1)%mo)%mo;
}
else
{
t[k++]=a[i++];
}
}
while(i<=m)t[k++]=a[i++];
while(j<=y)t[k++]=a[j++];
for(int i=x;i<=y;i++)
a[i]=t[i];
return (t1+t2+t3)%mo;
}
int main()
{
//freopen("match.in","r",stdin);
//freopen("match.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&A[i].v);
A[i].id=i;
}
for(int i=1;i<=n;i++)
{
scanf("%d",&B[i].v);
B[i].id=i;
}
sort(A+1,A+n+1,cmp);
sort(B+1,B+n+1,cmp);
for(int i=1;i<=n;i++)
x[A[i].id]=B[i].id;
LL ans=merge_sort(1,n,x);
cout<<ans<<endl;
return 0;
}