排列转换

排列转换

现在有两个长度为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
", sum / 2);
}
原文地址:https://www.cnblogs.com/7750-13/p/7401183.html