逆序对的两种算法【树状数组 / 归并排序】
2017-11-01 20:01
239 查看
对于数组A[1…n],求逆序对对数。
可根据数据范围离散化。
以下算法时间复杂度:O(n * log n)。
逆序对对数最大为n*(n-1)/2,结果经常要用long long保存。
利用树状数组统计比a[i]小的数个数s,逆序对个数加上i - 1 - s。
把a[i]计入树状数组,即结点i加1。
代码:
合并时,对于l <= i <= mid, mid + 1 <= j <= r,若a[i] > a[j],则a[i, mid]都比a[j]大,逆序对对数加上mid - i + 1。
代码:
可根据数据范围离散化。
以下算法时间复杂度:O(n * log n)。
逆序对对数最大为n*(n-1)/2,结果经常要用long long保存。
树状数组算法
逐一读入a[i]。利用树状数组统计比a[i]小的数个数s,逆序对个数加上i - 1 - s。
把a[i]计入树状数组,即结点i加1。
代码:
#include<bits/stdc++.h> using namespace std; const int MN = 1005;//MN根据数据决定 int n, i, x, ans, c[MN]; inline int lowbit(int x) { return x & (-x); } inline int sum(int x) { int s = 0; for(; x; x -= lowbit(x)) s += c[x]; return s; } inline void add(int x) { for(; x < n; x += lowbit(x)) c[x] ++; } int main() { scanf("%d", &n); memset(c, 0, sizeof(c)); for(i = 1, s = 0; i <= n; ++ i) { scanf("%d", &x); ans += i - 1 - sum(x); add(x); } printf("%d", ans); return 0; }
归并排序算法
二分时,将数组a[l, r]分为a[l, mid]与a[mid + 1, r](mid = (l + r) >> 1)分别归并排序。合并时,对于l <= i <= mid, mid + 1 <= j <= r,若a[i] > a[j],则a[i, mid]都比a[j]大,逆序对对数加上mid - i + 1。
代码:
#include<bits/stdc++.h> using namespace std; const int MN = 1005;//MN根据数据决定 int n, i, a[MN], b[MN], ans; inline void merge(int l, int r) { int mid = (l + r) >> 1, i, j, k; for(i = k = l, j = mid + 1; i <= mid && j <= r;) if (a[i] > a[j]) b[k ++] = a[j ++], ans += mid - i + 1; else b[k ++] = a[i ++]; for(; i <= mid; i ++) b[k ++] = a[i]; for(; j <= r; j ++) b[k ++] = a[j]; for(i = l; i <= r; i ++) a[i] = b[i]; } inline void merge_sort(int l, int r) { if (l >= r) return; int mid = (l + r) >> 1; merge_sort(l, mid); merge_sort(mid + 1, r); merge(l, r); } int main() { scanf("%d", &n); for(i = 1, s = 0; i <= n; ++ i) scanf("%d", &a[i]); ans = 0; merge_sort(1, n); printf("%d", ans); return 0; }
相关文章推荐
- 归并排序,树状数组 两种方法求逆序对
- 归并排序,树状数组 两种方法求逆序对
- 【算法】逆序对问题的四种解法(归并排序,BST,树状数组,线段树)及变形
- Ultra-QuickSort (poj 2299 归并排序 || 树状数组 求逆序对)
- 求逆序对模板题(完善模板:树状数组或归并排序)
- 【归并排序求逆序对个数】【树状数组求逆序对个数】
- hiho一下 第三十九周 #1141 : 二分·归并排序之逆序对 【归并排序----树状数组】
- E - Inversion-归并排序求逆序对/树状数组求逆序对
- POJ2299Ultra-QuickSort(归并排序 + 树状数组求逆序对)
- 两种数组逆序算法
- poj 2299 Ultra-QuickSort 【线段树 or 线段树+lazy or 树状数组 or 归并排序】 求逆序对
- 51 nod 1019 逆序数【归并排序||树状数组】
- hdoj 1394 Minimum Inversion Number 【线段树 or 线段树lazy or 树状数组 or 归并排序】【逆序对】
- [hdu]1394 Minimum Inversion Number -- 暴力求逆序、树状数组求逆序、线段树求逆序、归并排序求逆序
- nyoj 117 求逆序数【线段树 树状数组 归并排序】
- 二分·归并排序与树状数组之逆序对 hiho1141
- [洛谷P1908] 逆序对|归并排序|树状数组
- hdu 1394 Minimum Inversion Number (裸树状数组 求逆序数 && 归并排序求逆序数)
- 算法学习(二)——树状数组求逆序数
- poj 2299 求逆序对 树状数组 归并排序