题目
https://www.luogu.org/problemnew/show/P1966
思路
归并排序
可以发现如果将两个序列从小到大排序,距离一定是最小的,但这样浪费了很多次数。
所以我们想办法有排序的方法,把一个序列的顺序变成另一个序列的顺序。
在预处理时记下每个点的标号,然后排序,再使另一个序列对号入座。
最后,交换次数即为逆序对
代码
#include<cstdio>
#include<algorithm>
using namespace std;
typedef struct n
{
int num,ord;
}node;
node p1[100010],p2[100010];
int a[100010],b[100010],ans;
int cmp(node x,node y)
{
return x.num<y.num;
}
void work(int l,int r)
{
if(l>=r) return ;
int mid=(l+r)/2;
work(l,mid);
work(mid+1,r);
int i=l,j=mid+1,k=l;
while(i<=mid&&j<=r)
{
if(a[i]>a[j])
{
b[k++]=a[j++];
ans+=mid-i+1;
ans%=99999997;
}
else b[k++]=a[i++];
}
while(i<=mid) b[k++]=a[i++];
while(j<=r) b[k++]=a[j++];
for(int i=l;i<=r;i++)
a[i]=b[i];
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&p1[i].num);
p1[i].ord=i;
}
for(int i=1;i<=n;i++)
{
scanf("%d",&p2[i].num);
p2[i].ord=i;
}
sort(p1+1,p1+n+1,cmp);
sort(p2+1,p2+n+1,cmp);
for(int i=1;i<=n;i++)
a[p1[i].ord]=p2[i].ord;
work(1,n);
printf("%d",ans);
return 0;
}