Problem J: 幻化
Time Limit: 2 Sec Memory Limit: 128 MB
Submit: 18 Solved: 3
[Submit][Status][Web Board]
Description
遇见你是我一世的春暖花开,
从此清风明月浩瀚星海。
不论结局,很高兴认识你。
她给了他一个长度为n的整数序列a[],他还给了她另外一个长度为n的整数序列b[],现在他想通过每次交换a[i],a[j]使序列a变成b,但是每次交换的代价是|j-i|。
请问最少的代价是多少呢?(a序列和b序列均是[1,n]的一个全排列)
Input
第一行一个数字T代表测试的组数。(T<=10)
对于每组测试第一行一个数字n表示序列的长度(1<=n<=2*10^5);
接下来2行第一行n个数字a1,a2,a3...an (1<=ai<=n)
第二行n个数字b1,b2,b3...bn(1<=bi<=n)
Output
对于每个测试输出一个整数,占一行,表示把a[]变成b[]所需要最少的交换代价。
Sample Input
2
4
1 2 3 4
4 3 2 1
4
2 1 4 3
1 2 3 4
Sample Output
4
2
HINT
对于第一组样例1 4交换,2 3交换,代价是4
第二组样例2 1交换,3 4交换,代价是2
题意:有两个长度为n的排列p和s。要求通过交换使得p变成s。交换 pi 和 pj 的代价是|i-j|。要求使用最少的代价让p变成s。
考虑两个数字pi和pj,假如交换他们能使得pi到目标的距离减少,pj到目标的距离减少。那么应该交换他们,这是一个必要的操作,也是答案的下界。
如果每一次都能找到这样的两个数字,那么答案就是排列p中的每个数字在排列s的位置的距离差之和/2.这显然是答案的下界。
现在考虑证明这个下界是可以构造出来的。
考虑排列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,使得它们交换之后到目标的距离都减小了。
先将s映射成1-n的顺序排列,再将p根据同一映射函数映射成新的序列,得到新问题与原问题等价.
现在我们要做的就是将pi移到i位置上,我们可以先从最小的pi开始移动,这样当我们移动任何一个pi时,假设pi当前位置为x,我们都能保证pi<=x,如果pi==x,那么移动结束,否则我们可以一直将pi向左交换,使得其越来月接近目标位置,在这个过程中,pi是不会产生更多代价的,但是和pi交换的元素有可能产生更多代价,因此我们每次必定要挑选pj>=x的pj去和pi交换,这样才能保证总代价不变大,可以证明[i,x-1]区间内一定存在pj>=x.(可以用抽屉原理证明)
#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;
}
原文地址:https://www.cnblogs.com/Roni-i/p/8996451.html
时间: 2024-11-05 15:59:31