POJ 2299 Ultra-QuickSort
今晚学习了逆序数,基本上照着别人的程序写的。利用归并排序来统计逆序数。
当归并两条有序链时,可以同时计算逆序数。
当left<=i<=mid,mid+1<=j<=right,如果有a[i]>a[j],这样的说明在a的前段中i...mid的元素都比a[j]大,于是逆序数+=mid-i +1;如果a[i]<a[j],这样的发生说明属于正常排序.
这题如果是用O(n^2)的方法统计会超时,注意要用long long保存,用long会WA
#include <iostream> #include <cstring> #include <cstdio> #define MAX 500005 using namespace std; long long tmp[MAX]; long long array[MAX]; long long ans; void merge_sort(int left, int right); void merge(int left, int mid, int right); int main() { int n; while (cin >> n && n) { for (int i = 0; i < n; i++) scanf("%lld", &array[i]); ans = 0; merge_sort(0, n-1); cout << ans << endl; } return 0; } void merge_sort(int left, int right) { if (left < right) { int mid = (left + right)/2; merge_sort(left, mid); merge_sort(mid+1, right); merge(left, mid, right); } } void merge(int left, int mid, int right) { int begin1, begin2; int end1, end2; int i = 0; begin1 = left; end1 = mid; begin2 = mid+1; end2 = right; while (begin1 <= end1 && begin2 <= end2) { if (array[begin1] <= array[begin2]) tmp[i++] = array[begin1++]; else { tmp[i++] = array[begin2]; ans += mid - begin1 + 1; //计算逆序数 begin2++; } } while (begin1 <= end1) tmp[i++] = array[begin1++]; while (begin2 <= end2) tmp[i++] = array[begin2++]; for (int j = 0; j < i; j++) array[left+j] = tmp[j]; }