zoukankan      html  css  js  c++  java
  • codeforces#324(div2) E. Anton and Ira 贪心

    codeforces#324(div2) E. Anton and Ira  贪心

    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.

    题意:给两个1~n的序列,将序列p通过k次交换变成序列s,每次交换的代价为|i-j|,求最小交换代价,输出交换方案。

    思路:本来看到1~n,应该想到置换,不过这题和置换并没有什么关系。。。

    基本思路是这样,将一个数通过交换到达它该去的位置的过程中无论交换方式如何,代价是不变的。比如4 5 1 2 3,4要到达2所在的位置那么swap(1,3)+swap(3,4)=swap(1,2)+swap(2,4)(代价相等),但是相同的代价不同的交换方式造成的结果是不一样的,swap(1,3)使1更接近原位置了,swap(1,2)却使5偏离更原位置了,因此贪心出现在这里,我们要使在把每个数移动到它的位置时使得其它数更接近它的原位置,也就是对于每个能往右移动的,在移到原位置的途中把能往左移动也移动。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    
    int n;
    int p[maxn],s[maxn];
    int id[maxn];
    int cost;
    struct Node
    {
        int x,y;
    };
    vector<Node> ans;
    
    int solve(int *a,int n)
    {
        if(n==1) return 0;
        int x,y;
        REP(i,1,n){
            if(a[i]==n){
                x=i;break;
            }
        }
        int cost=0;
        REP(i,x+1,n){
            if(a[i]<=x){
                ans.push_back({x,i});
                swap(a[x],a[i]);
                cost+=abs(x-i);
                x=i;
            }
        }
        return cost+solve(a,n-1);
    }
    
    int main()
    {
        while(cin>>n){
            ans.clear();
            REP(i,1,n) scanf("%d",&p[i]);
            REP(i,1,n) scanf("%d",&s[i]),id[s[i]]=i;
            REP(i,1,n) p[i]=id[p[i]];
            //REP(i,1,n) cout<<p[i]<<" ";cout<<endl;
            cost=solve(p,n);
            printf("%d
    %d
    ",cost,(int)ans.size());
            for(int i=0;i<ans.size();i++) printf("%d %d
    ",ans[i].x,ans[i].y);
        }
        return 0;
    }
    View Code
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    Debian 添加用户
    如何让安卓手机访问内网服务器?
    数据库权限
    CentOs
    批量导入sql文件。
    使用Navicat Premium连接mysql数据库
    git 合包
    linux 下文件打包
    git 分支管理
    gcc8.2安装
  • 原文地址:https://www.cnblogs.com/--560/p/4861451.html
Copyright © 2011-2022 走看看