POJ2299《Ultra-QuickSort》方法:归并排序找逆序数

题目大意:求一个数的逆序数,比如54321的逆序数为4+3+2+1+0=10,逆序数 = 在只交换相邻两数的前提下,需要的交换次数。

解题思路:因为这题数据量为50W,时间限制为7000ms,用冒泡排序找相邻交换次数肯定超时,因此用归并排序找相邻交换次数。之所以不用快速排序,是因为它不符合相邻元素交换的要求。

// 3748k 2454ms #include using namespace std; const int inf = 1000000000; __int64 ans; // 逆序数 void combine(int *a, int top, int mid, int end) { int len1 = mid-top+1; int len2 = end-mid; int *left = new int[len1+2]; int *right = new int[len2+2]; int i, j, k; for (i = 1; i <= len1; ++i) left[i] = a[top-1+i]; left[len1+1] = inf; //inf数参照,必须要加 for (j = 1; j <= len2; ++j) right[j] = a[mid+j]; right[len2+1] = inf; i = j = 1; for (k=top; k <= end; ) { if (left[i] <= right[j]) { a[k++] = left[i++]; } else { a[k++] = right[j++]; ans += len1-i+1; //要交换大数的交换次数 } } delete left; delete right; } void mergeSort(int *a, int top, int end) { if (top < end) { int mid = (top+end) / 2; mergeSort(a, top, mid); mergeSort(a, mid+1, end); combine(a, top, mid, end); } } int main() { //freopen("temp.txt", "r", stdin); int n; while (cin >> n && n!=0) { ans = 0; int *a = new int[n+1]; for (int i = 1;i <= n; ++i) cin >> a[i]; mergeSort(a, 1, n); printf("%I64d\n", ans); //输出64位的整数,无法用cout delete a; } return 0; }

你可能感兴趣的:(POJ)