codeforces 584 E:映射

第一步要做的是映射,把目标序列映射成1~n,然后按照这个映射规则把当前序列映射一下

接下来也稍微有点贪心的意思吧:从1开始放置,位置在它之前的元素,如果找到的元素不在该在的位置,并且和当前元素互换后,找到的元素的目标位置在当前元素的左边,才换

似乎有点抽象。。。就拿样例来说吧

映射后当前序列是3 2 4 1

目标序列是1 2 3 4

从1开始找,找它之前的,不在该在的位置的元素

第一个找到3,在1号位置,但是我们不换

因为现在1在4号位置,换了的话3变到4号位置,3将来还是要往左换才能到达的,这里就有浪费的步骤,继续找

找到4,在2号位置,我们选择换

因为换了之后4变到4号位置,满足条件,虽然1没有直接回到1号位置,但是总体来看这是最优的

不用担心找不到这样的元素。

因为我们操作的本就是不在正确位置的元素,这样的情况不会成单出现,就好像5在2号位置,那2肯定不在正确的位置。当然,2也可能在5右边,那这样2又占据了一个比5大的位置,该位置的主人又……如此下去肯定要有一个符合要求的元素在5左边才能结束这个循环

#include"cstdio"
#include"queue"
#include"cmath"
#include"stack"
#include"iostream"
#include"algorithm"
#include"cstring"
#include"queue"
#include"map"
#include"vector"
#define ll long long
#define mems(a,b) memset(a,b,sizeof(a))
#define ls pos<<1
#define rs pos<<1|1

using namespace std;
const int MAXN = 2005000;
const int MAXE = 2050;
const int INF = 0x3f3f3f3f;
int f[MAXE],x[MAXE],y[MAXE],pos[MAXE];

struct node{
    int x,y;
    node(){}
    node(int a,int b):x(a),y(b){}
}ans[MAXN];

int main(){
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&x[i]);
    for(int i=1;i<=n;i++) scanf("%d",&y[i]);
    for(int i=1;i<=n;i++) f[y[i]]=i;
    for(int i=1;i<=n;i++){
        x[i]=f[x[i]];
        pos[x[i]]=i;
    }
    //for(int i=1;i<=n;i++) cout<<x[i]<<' ';
    int cost=0,step=0,cnt=0;
    for(int i=1;i<=n;i++){  ///number
        if(pos[i]==i) continue;
        while(pos[i]!=i){
            for(int j=1;j<pos[i];j++){   ///pos
                if(x[j]>=pos[i]){
                    cost+=pos[i]-j;
                    step++;
                    ans[cnt++]=node(j,pos[i]);
                    int t=pos[i];
                    pos[i]=j;pos[x[j]]=t;
                    swap(x[t],x[j]);
                }

            }
        }
    }
    cout<<cost<<endl;
    cout<<step<<endl;
    for(int i=0;i<cnt;i++) cout<<ans[i].y<<' '<<ans[i].x<<endl;

    return 0;
}
原文地址:https://www.cnblogs.com/luxiaoming/p/5137652.html