排列转换
现在有两个长度为n的排列p和s。要求通过交换使得p变成s。交换 pipi 和 pjpj 的代价是|i-j|。要求使用最少的代价让p变成s。
Input单组测试数据。
第一行有一个整数n (1≤n≤200000),表示排列的长度。
第二行有n个范围是1到n的整数,表示排列p。每个整数只出现一次。
第三行有n个范围是1到n的整数,表示排列s。每个整数只出现一次。Output输出一个整数,表示从排列p变到s最少要多少代价。
Sample Input
样例输入1
4
4 2 1 3
3 2 4 1
Sample Output
样例输出1
3
题目大意 :给你一初始组序列和一组既定序列,求从初始序列到既定序列所用最小的|i-j|值的和。
题目分析 :
考虑排列p中最后一个位置不对的数字,不妨设为pj,他的目标位置是pi,那么如果p[i+1,j]中有任意一个数的目标是pk(k<i),那么可以进行必要交换。
假设没有这样的一个数字使得他的目标是pk,一共有(j-i-1)个数,(j-i-2)个空,根据鸽巢原理,显然不存在这样的情况。
也就是说,对于排列p中最后一个位置不对的数字pj,目标位置是pi,pi总能在p[i+1,j]中找到一个数字pk,使得它们交换之后到目标的距离都减小了。
题目收获 :仍存疑问。
AC代码:
#include <iostream>
#include <cstdio>
#include <math.h>
using namespace std;
int ans[200005];
int main()
{
int n, x;
long long sum = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &x), ans[x] = i;
for (int i = 1; i <= n; i++)
{
int y = 0;
scanf("%d", &y);
sum += abs(ans[y] - i);
}
printf("%lld\n", sum / 2);
}