POJ 2299 Ultra-QuickSort
本例主要是利用归并排序求逆序对数
只要在归并排序的基础上添加一行计数即可
View Code
1 //--------------------------------------- 2 // 利用归并排序(MergeSort)求逆序对数 3 // http://baike.baidu.com/view/90797.htm 4 // 归并排序主要采用分治思想,分为若干子序列排序 5 // 时间空间复杂度和QuickSort相同,但更稳定 6 //--------------------------------------- 7 #include <cstdio> 8 #include <cstring> 9 using namespace std; 10 #define LL long long 11 const int M = 500005; 12 LL a[M], ans, t[M]; 13 14 void MergeSort(LL L, LL R) 15 { 16 // 将序列每相邻两个数字进行归并操作(merge),形成floor(n/2)个序列,排序后每个序列包含两个元素 17 // 将上述序列再次归并,形成floor(n/4)个序列,每个序列包含四个元素 18 // 重复步骤2,直到所有元素排序完毕 19 if (L == R) return; 20 LL mid = (L + R) / 2; 21 MergeSort(L, mid); // 排序左子区间 22 MergeSort(mid + 1, R); // 排序右子区间 23 LL i = L, j = mid + 1, p = 0; 24 // 打印每个待排序区间中所有元素 25 for (LL i = L; i <= R; i++) 26 printf("%d ", a[i]); 27 printf("\n"); 28 // 等待左右子区间合并 29 while (i <= mid && j <= R) 30 { 31 if (a[i] > a[j]) 32 { 33 // POJ 2299就是在归并排序基础上加这一句 34 // 当a[i]>a[j],a[i]以及以后的数都可以和a[j]形成逆序对 35 ans += mid - i + 1; 36 t[++p] = a[j++]; // a[j]进入合并Merge序列 37 } 38 else 39 { 40 t[++p] = a[i++]; 41 } 42 } 43 // 左右子区间剩余元素进入合并序列 44 while (i <= mid) t[++p] = a[i++]; 45 while (j <= R) t[++p] = a[j++]; 46 // 讲合并序列t赋予a,当前区间结束 47 p = 0; 48 for (LL i = L; i <= R; i++) a[i] = t[++p]; 49 } 50 51 int main() 52 { 53 int n; 54 while (scanf("%d", &n), n) 55 { 56 ans = 0; 57 for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); 58 MergeSort(1, n); 59 printf("%lld\n", ans); 60 } 61 return 0; 62 } 63 /* 64 Sample Input: 65 5 66 9 1 0 5 4 67 3 68 1 2 3 69 0 70 */