POJ-2299 Ultra-QuickSort 逆序对数量

  题目链接: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 }

 

你可能感兴趣的:(Quicksort)