题目链接:http://poj.org/problem?id=2299
给你一个升序列,然后要你只能交换相邻的两个数把这个序列按升序排列,求最少需要交换多少次。
不管怎么样,只要存在ai>aj(i<j),那么这两个数之间必须要交换。任意两个数不影响其它数之间的大小位置关系,所以可以看出就是求逆序对数量。求逆序对数量有很多方法,树状数组或者线段树优化等,但是用合并排序的方法更方便,即在合并左儿子和右儿子的时候,统计左儿子比右儿子大的数的个数即可,复杂度O(log(n))。
合并排序版:
1 //STATUS:C++_AC_391MS_3688KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<math.h> 6 #include<iostream> 7 #include<string> 8 #include<algorithm> 9 #include<vector> 10 #include<queue> 11 #include<stack> 12 #include<map> 13 using namespace std; 14 #define LL __int64 15 #define pii pair<int,int> 16 #define Max(a,b) ((a)>(b)?(a):(b)) 17 #define Min(a,b) ((a)<(b)?(a):(b)) 18 #define mem(a,b) memset(a,b,sizeof(a)) 19 #define lson l,mid,rt<<1 20 #define rson mid+1,r,rt<<1|1 21 const int N=500010,INF=0x3f3f3f3f,MOD=1999997; 22 const LL LLNF=0x3f3f3f3f3f3f3f3fLL; 23 24 int num[N],temp[N]; 25 int n; 26 LL ans; 27 28 void sort(int l,int r) 29 { 30 if(l==r)return; 31 int i,j,k,mid=(l+r)>>1; 32 sort(l,mid); 33 sort(mid+1,r); 34 for(i=k=l,j=mid+1;i<=mid && j<=r;){ 35 if(num[i]<num[j]){ 36 ans+=j-mid-1; 37 temp[k++]=num[i++]; 38 } 39 else temp[k++]=num[j++]; 40 } 41 while(i<=mid){ 42 ans+=j-mid-1; 43 temp[k++]=num[i++]; 44 } 45 while(j<=r) 46 temp[k++]=num[j++]; 47 for(i=l;i<=r;i++) 48 num[i]=temp[i]; 49 } 50 51 int main() 52 { 53 // freopen("in.txt","r",stdin); 54 int i,j; 55 while(~scanf("%d",&n) && n) 56 { 57 ans=0; 58 for(i=0;i<n;i++) 59 scanf("%d",&num[i]); 60 61 sort(0,n-1); 62 printf("%I64d\n",ans); 63 } 64 return 0; 65 }