Codeforces 584E Anton and Ira

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.


解题思路:本题有一点处理技巧,将第二个排列看成是1->n的整数,然后将第一组排列重新映射,这样我们的问题便转换成将一组排列通过交换操作转化成递增序列的最少交换代价,并且输出相应的交换方案。问题经过这么一转化,我们便很容易得出如下的解决方案:首先将最大的元素交换到其相应的位置,则在交换的过程中我们可以和在当前最大元素索引后面且其相应的值小于等于当前最大元素所在数组的索引位置,我们逐步通过这样的交换操作将最大的元素交换到其相应的位置上,很容易得到无论交换多少次这个交换代价总是固定额的,即最大元素期初所在位置与最大元素最终所在位置的索引值差的绝对值,但是我们在将最大元素交换到其相应的位置时也将其后面元素仍在其相应索引位置之后的元素向前移动了,这样我们保证了在将最大元素移动到其相应位置的同时将另外一些元素向前进行了移动,但是待与最大元素交换的元素的值和最大元素的当前位置要存在一个<=的关系,一旦大于则相当于将待交换的元素先向前移动然后向后移动,这样的策略肯定不是最优的,因此舍弃满足大于关系的元素。感觉自己说的都是废话,其实看代码一看就懂了,便是将当前元素移动到其相应的位置的同时,将一些需要向前移动的元素向前移动一下,这样使得我们当前元素交换代价不变的情况下,使接下来将要移动的元素的情况变的更好了。于是我们可以以元素值从大到小的顺序安置元素,然后从计算最少交换代价和,并且保存交换的方案,其实代码很简单,但这道题确实是需要一个思维的过程。

#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
const int maxn = 2010;
typedef long long ll;
int a[maxn], b[maxn], trans[maxn];
int s[2*1000010], e[2*1000010];
int cnt;
ll  ans;

// 其实最优的决策方案便是在放置最大元素的同时改善其他元素所在的位置,使得接下来的
// 交换操作所需要的代价变的更少,这样我们得到的最终的交换代价和便是最小的
int main() {

    //freopen("aa.in", "r", stdin);
    int n;
    ans = 0;
    cnt = 0;
    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]);
        trans[b[i]] = i;
    }
    for(int i = 1; i <= n; ++i) {
        a[i] = trans[a[i]];
    }
    for(int i = n; i >= 1; --i) {
        if(a[i] == i) continue;
        int p;
        for(int j = 1; j <= n; ++j) {
            if(a[j] == i) {
                p = j;
                break;
            }
        }
        int j = p + 1;
        while(p != i) {
            if(a[j] <= p) {
                swap(a[p], a[j]);
                s[cnt] = j;
                e[cnt] = p;
                cnt++;
                ans += j - p;
                p = j;
            } else {
                j++;
            }
        }
    }
    printf("%I64d\n", ans);
    printf("%d\n", cnt);
    for(int i = 0; i < cnt; ++i) {
        printf("%d %d\n", s[i], e[i]);
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值