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.
Ultra-QuickSort produces the output
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(归并排序)