http://blog.acmj1991.com/?p=776
思路:求逆序数
思路:开始理解错了,以为是用最少的交换次数使数列变成递增数列。后来才知道理解错了,但是可以吧这种想法的代码贴出来,其实就是总数减去环的数量
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxN 1010
int cnt,n,key[maxN],b_key[maxN];
void low(int l,int r)
{
if(l==r)return ;
int mid=(l+r)/2;
low(l,mid),low(mid+1,r);
int st=l,en=mid+1,q=l;
while(q<=r&&st<=mid&&en<=r)
{
if(key[st]<=key[en])
b_key[q++]=key[st++];
else{
cnt+=mid-st+1;
b_key[q++]=key[en++];
}
}
if(st<=mid)
while(q<=r)b_key[q++]=key[st++];
if(en<=r)
while(q<=r)b_key[q++]=key[en++];
for(int i=l;i<=r;i++)
key[i]=b_key[i];
}
int main()
{
int t,k=1;
scanf("%d",&t);
while(t--)
{
cnt=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&key[i]);
low(1,n);
printf("Scenario #%d:\n%d\n\n",k++,cnt);
}
}
求最少移动步数的代码
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; #define maxN 1010 int key[maxN],f[maxN],vist[maxN]; int low(int l,int r,int x) { if(l==r)return l; int mid=(l+r)/2; if(x<=key[mid]) return low(l,mid,x); else return low(mid+1,r,x); } int main() { freopen("1.txt","r",stdin); int n,t; scanf("%d",&t); while(t--) { memset(vist,0,sizeof(vist)); memset(key,0,sizeof(key)); scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&f[i]); key[i]=f[i]; } sort(key,key+n); int sum=0; for(int i=0;i<n;i++) if(!vist[i]&&f[i]!=key[i]){ int m=i; sum++; while(!vist[m]){ vist[m]=1; m=low(0,n-1,f[m]); } } printf("%d\n",n-sum); } }