POJ2299 UltraQuickSort 逆序对数量

  题目链接: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 }
原文地址:https://www.cnblogs.com/zhsl/p/2838570.html