求逆序對個數(分治)
阿新 • • 發佈:2019-01-02
求逆序對個數
在歸併排序(從大到小)的合併過程前,對兩個分支進行逆序對數的計算(該計算過程為O(n))
#include <cstdio> #include <iostream> #include <algorithm> #define N 100005 using namespace std; int a[N], b[N]; void Merge(int a[], int s, int m, int e, int tmp[]) { int p = 0, p1 = s, p2 = m + 1; //開始合併 while (p1 <= m && p2 <= e) { if (a[p1] > a[p2]) tmp[p++] = a[p1++]; else tmp[p++] = a[p2++]; } while (p1 <= m) tmp[p++] = a[p1++]; while (p2 <= m) tmp[p++] = a[p2++]; for (int i = 0; i < p; i++)//把結果拷貝到全域性陣列a中 a[i + s] = tmp[i]; } long long cal(int a[], int s, int m, int e, int tmp[]) { int i = s, j = m + 1; long long result = 0; while (i <= m && j <= e) { if (a[i] > a[j]) { result += e - j + 1; i++; } else j++; } return result; } long long Merge_sort(int a[], int s, int e, int tmp[]) { long long cnt = 0; if (e > s) { int m = s + (e - s) / 2; cnt += Merge_sort(a, s, m, tmp); cnt += Merge_sort(a, m + 1, e, tmp); cnt += cal(a, s, m, e, tmp); Merge(a, s, m, e, tmp); } return cnt; } int main() { long long ans = 0; int n; scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &a[i]); ans = Merge_sort(a, 0, n - 1, b); printf("%lld\n", ans); return 0; }