第一步要做的是映射,把目标序列映射成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; }