poj2299解题报告(归并排序求逆序数)
2015-04-29 14:15
459 查看
POJ 2299,题目链接http://poj.org/problem?id=2299
题意:
给出长度为n的序列,每次只能交换相邻的两个元素,问至少要交换几次才使得该序列为递增序列。思路:
其实就是求逆序数,那么直接向到的就是冒泡了,交换一次,记录一次即可。但是n的范围达到50W,冒泡O(n^2)的复杂度铁定超时。然后、、、发现曾经微软有一道笔试题类似就是求逆序数的,对,没错,用归并。
例:合并两个序列(1,3,5)(2,4,6),新序列第二个元素是2,那么它和它前面的3、5形成了逆序数对,所以....
代码:
//3880K 391MS #include <cstdio> #include <algorithm> int buf[500000]; int ret[500000]; unsigned long long count; void mergeArray(int *a, int first, int mid, int last, int *ret) { int i = first, j = mid+1, k =0; int m = mid, n = last; while(i<=m && j<=n){ if (a[i] <= a[j]) { ret[k++] = a[i++]; } else { ret[k++] = a[j++]; count += m-i+1; //记录 } } while(i<=m) ret[k++] = a[i++]; while(j<=n) ret[k++] = a[j++]; for (int i=0;i<k; ++i) a[first+i] = ret[i]; } void mergeSort(int data[], int first, int end, int *ret) { if (first < end) { int mid = (first + end)/2; mergeSort(data, first, mid, ret); mergeSort(data, mid+1, end, ret); mergeArray(data, first, mid, end, ret); } } int main() { int num; while (true) { scanf("%d", &num); if (num <= 0) break; for (int i=0; i<num; ++i) scanf("%d", &buf[i]); count = 0; mergeSort(buf, 0, num-1, ret); printf("%lld\n", count); } return 0; }
相关文章推荐
- nlogn求逆序数 POJ 2299解题报告
- poj 2299 归并排序求逆序对 解题报告
- Pku acm 2299 Ultra-QuickSort 排序算法解题报告(四)----归并排序(MegerSort)求逆序数
- POJ 2299 Ultra-QuickSort (求逆序数:离散化+树状数组或者归并排序求逆序数)
- poj 2299 归并排序求逆序数 (可做模板)
- POJ训练计划2299_Ultra-QuickSort(归并排序求逆序数)
- poj——2299(归并排序求逆序数对)
- POJ训练计划2299_Ultra-QuickSort(归并排序求逆序数)
- poj_2299 归并排序找逆序数
- POJ - 2299 Ultra-QuickSort解题报告
- POJ 2299 解题报告
- POJ2299-Ultra-QuickSort (归并排序求逆序数)
- 归并排序与逆序对问题---(解题报告)POJ1804---Brainman
- poj解题报告——2299
- poj 2299 Ultra-QuickSort(归并排序求逆序数)
- poj-2299 Ultra—QuickSort(归并排序求逆序数)
- Poj-2299 [用归并排序求逆序数的个数]
- POJ 2299 Ultra-QuickSort (归并排序、逆序数)
- Poj 2299 Ultra-QuickSort(归并排序求逆序数)
- 归并排序求逆序数(POJ 1804,POJ 2299,HDU 4911)