Ultra-QuickSort——[归并排序分治求逆序对]

Posted kiraa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ultra-QuickSort——[归并排序分治求逆序对]相关的知识,希望对你有一定的参考价值。

Description

技术分享  In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence 
9 1 0 5 4 ,

Ultra-QuickSort produces the output 
0 1 4 5 9 .

  Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.

Input

  The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.

Output

  For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.

Sample Input

5
9
1
0
5
4
3
1
2
3
0

Sample Output

6
0
解题思路:
  本题揭示了排序的本质——消除逆序对。逆序对,是指对于满足 当i<j时,a[i]>a[j]的序偶(a[i],a[j])。可以证明,交换序列中任意两个
相邻元素,逆序对增加或减少一。那么对于一个给定的序列,按一次交换一对相邻元素的方法,最少需要要交换的次数等于此序列中逆序对的数目
那么问题就变成了如何求给定序列的逆序对。可以采用分治的方法:
  整个序列逆序对数=左半序列逆序对数+右半序列逆序对数+前一个元素在左半序列,后一个元素在右半序列的逆序对数。
  再细考虑可以发现,这个过程可以在归并排序的同时完成,时间复杂度为O(NlogN).

注意
:可以简单计算一下,n个元素的排列逆序对数最多有 n(n-1)/2个,需要用到long long。

代码如下:
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <ctime>
 5 using namespace std;
 6 #define print_time_ printf("time : %f\n",double(clock())/CLOCKS_PER_SEC)
 7 #define maxn 500000
 8 int A[maxn+5];
 9 
10 typedef long long LL;
11 LL DC(int a,int N){
12     int mid=a+N/2-1;
13     int b=a+N-1;
14     if(N==1)
15         return 0;
16     
17     LL x1=DC(a, N/2);
18     LL x2=DC(mid+1,b-mid);
19     LL x3=0;
20     int *B=new int[N];
21     int i=a,j=mid+1,p=0;
22     for(;i<=mid&&j<=b&&p<N;p++){
23         if(A[i]<=A[j]){
24             B[p]=A[i++];
25         }
26         else {
27             B[p]=A[j++];
28             x3+=mid-i+1;
29         }
30     }
31     while(i<=mid){B[p++]=A[i++];}
32     while(j<=b){B[p++]=A[j++];}
33     memcpy(A+a, B, N*sizeof(int));
34     delete [] B;
35     return x1+x2+x3;
36 }
37 int main() {
38     int n;
39     while(scanf("%d",&n)==1&&n){
40         for(int i=0;i<n;i++)
41             scanf("%d",&A[i]);
42         printf("%lld\n",DC(0, n));
43     }
44     //print_time_;
45     return 0;
46 }

 



以上是关于Ultra-QuickSort——[归并排序分治求逆序对]的主要内容,如果未能解决你的问题,请参考以下文章

POJ - 2299 Ultra-QuickSort(归并排序)

POJ - 2299 - Ultra-QuickSort = 归并排序 + 逆序对 / 树状数组

POJ2299 Ultra-QuickSort

POJ2299----Ultra-QuickSort

[归并排序]Ultra-QuickSort

Ultra-QuickSort (归并排序,逆序数)