【Codeforces Round 324 (Div 2)E】【贪心 构造】Anton and Ira 全排列交换 最小距离成本

84 篇文章 5 订阅
24 篇文章 0 订阅
E. Anton and Ira
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Anton loves transforming one permutation into another one by swapping elements for money, and Ira doesn't like paying for stupid games. Help them obtain the required permutation by paying as little money as possible.

More formally, we have two permutations, p and s of numbers from 1 to n. We can swap pi and pj, by paying |i - j| coins for it. Find and print the smallest number of coins required to obtain permutation s from permutation p. Also print the sequence of swap operations at which we obtain a solution.

Input

The first line contains a single number n (1 ≤ n ≤ 2000) — the length of the permutations.

The second line contains a sequence of n numbers from 1 to n — permutation p. Each number from 1 to n occurs exactly once in this line.

The third line contains a sequence of n numbers from 1 to n — permutation s. Each number from 1 to n occurs once in this line.

Output

In the first line print the minimum number of coins that you need to spend to transform permutation p into permutation s.

In the second line print number k (0 ≤ k ≤ 2·106) — the number of operations needed to get the solution.

In the next k lines print the operations. Each line must contain two numbers i and j (1 ≤ i, j ≤ ni ≠ j), which means that you need to swap pi and pj.

It is guaranteed that the solution exists.

Sample test(s)
input
4
4 2 1 3
3 2 4 1
output
3
2
4 3
3 1
Note

In the first sample test we swap numbers on positions 3 and 4 and permutation p becomes 4 2 3 1. We pay |3 - 4| = 1 coins for that. On second turn we swap numbers on positions 1 and 3 and get permutation 3241 equal to s. We pay |3 - 1| = 2 coins for that. In total we pay three coins.

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<iostream>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}
template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}
const int N=2020,M=0,Z=1e9+7,ms63=1061109567;
int casenum,casei;
int n;
int a[N],b[N],c[N*N],d[N*N];
int go[N],from[N];
int main()
{
	while(~scanf("%d",&n))
	{
		for(int i=1;i<=n;i++)scanf("%d",&a[i]);	
		for(int i=1;i<=n;i++)scanf("%d",&b[i]);
		int ans=0;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)if(a[i]==b[j])
			{
				go[i]=j;//i->j
				from[j]=i;//j<-i
				break;
			}
			ans+=abs(go[i]-i);
		}
		ans>>=1;
		int tim=0;
		for(int i=1;i<=n;i++)
		{
			if(go[i]!=i)
			{
				//应该到位置i的数现在是在位置j
				int j=from[i];
				while(go[i]!=i)
				{
					//位置k的数想到到达位置j的右侧
					int k;for(k=i;k<=n;k++)if(go[k]>=j)break;
					c[++tim]=j;
					d[tim]=k;
					int tmp=go[j];
					go[j]=go[k];
					go[k]=tmp;
					j=k;
					//这里不用交换from值,因为发现其实不影响
				}
			}
		}
		printf("%d\n",ans);
		printf("%d\n",tim);
		for(int i=1;i<=tim;i++)printf("%d %d\n",c[i],d[i]);
	}
	return 0;
}
/*
【题意】
给你2个长度为n(1<=n<=2000)全排列a[],b[],我们可以操作a[]。
对于每次操作,可以交换任意两个位置(i,j)上的数,并把该次操作的成本记为abs(i-j)。
问你如何操作,可以使得我们最终能够把第一个全排列转变为第二个。

【类型】
贪心 构造

【分析】
设初始位置i的数想到到达的位置为go[i],
那么这道题的答案就是∑(abs(i-go[i]))。
为什么是这样呢?

1,必要性:
显然这个是最小的交换成本。因为每次付出一个单位的成本代价,
从效果上讲,我们只是使得一个位置的数右移1,另一个位置的数左移1。
答案肯定不会比∑(abs(i-go[i]))更优。

于是我们只要构造出对于任意a[],b[],交换成本都是∑(abs(i-go[i]))的交换方式即可,
这也就对应着——2,充分性:

我是这么构造的,可以保证每个数从头到尾都没有被多移动——
我们从前向后扫描,对于每个位置i上的数,我们看看其是否恰好应该放在这里。
如果不是,那么找到那个恰好要放在这里的数a[j],确定其位置为j。
a[j]肯定是要左移的。
那么对应着哪个数和a[j]交换呢?
我们发现,i左边的数都是有序的,i~j-1的数的个数设为num个。
因为a[j]要移到a[i],a[j]∈[i,j-1]区间,
所以肯定有一个[i,j-1]上的数a[k],不属于这个区间,而是属于[j,n]区间
a[k]至少要移到j上,所以,移动到j上的话,保证了移动成本不冗余;
同时,a[j]至少要移动i上,所以,移动到k上的话,移动成本也不会冗余。
这样重复下去,就可以AC这道题了。

*/


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值