★★51nod 1574 排列转换 (贪心思维题)

来源:互联网 发布:机械力学分析软件 编辑:程序博客网 时间:2024/05/29 05:07


1574 排列转换
 收藏
 关注

现在有两个长度为n的排列p和s。要求通过交换使得p变成s。交换 pi 和 pj 的代价是|i-j|。要求使用最少的代价让p变成s。


Input
单组测试数据。第一行有一个整数n (1≤n≤200000),表示排列的长度。第二行有n个范围是1到n的整数,表示排列p。每个整数只出现一次。第三行有n个范围是1到n的整数,表示排列s。每个整数只出现一次。
Output
输出一个整数,表示从排列p变到s最少要多少代价。
Input示例
样例输入144 2 1 33 2 4 1
Output示例
样例输出13
System Message (题目提供者)

好题。。584e

先放一下讨论区里wc大神的题解:

猜了一下结论,居然对了..........

具体操作是:
假设排列s是1,2,3,...,n
k为排列p中最大的 没有放到正确位置的数,k的位置为pos
k的右边一定有一个数x<=pos(因为<=pos的数有pos个,不可能全挤在pos-1个位置里)
交换k和x,两个数都离目标更近了且没有走远路.
重复这个步骤

所以无论过程怎样,结果都是一样的,都是从当前位置换到应该去的位置,根据上面的鸽巢原理,在他当前位置到应该去的位置肯定会有“跳板”帮助他交换。。

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int maxn = 2e5 + 5;int a[maxn], b[maxn];int main(){    int n;    while(~scanf("%d", &n))    {                long long ans = 0;        int x;        //这里是映射,记录a数组每个“值”所在的"位置",从a变到b跟从a变到b是一样的。。        for(int i= 1; i <= n; i++)            scanf("%d", &x), a[x] = i;        //这里看每个值应该在位置如果在当前位置后面就可以交换过去        for(int i = 1; i <= n; i++)        {            scanf("%d", &x);            if(a[x] >= i) ans += a[x]-i;        }        printf("%lld\n", ans);    }    return 0;}

不知道为什么下面这个原理。。还要除以2。。希望大佬教一下。。

#include<iostream>#include<stdlib.h>using namespace std;const int MAXN = 2e5+10;int a[MAXN];int main(){    int n,x;    long long ans=0;    cin>>n;    for(int i=0;i<n;++i){cin>>x;a[x]=i;}    for(int i=0;i<n;++i){cin>>x;ans+=abs(a[x]-i);}    cout<<ans/2<<endl;}


原创粉丝点击