AKOJ-2021-逆序對(歸並,二分)
阿新 • • 發佈:2019-01-18
bits 組合 逆序數 數組合並 ++ return 尋找 end 排序
鏈接:https://oj.ahstu.cc/JudgeOnline/problem.php?id=2021
題意:
在一個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麽它們就稱為一個逆序。一個排列中逆序的總數就稱為這個排列的逆序數。
現在,給你一個N個元素的序列,請你判斷出它的逆序數是多少。
比如 1 3 2 的逆序數就是1。
思路:
求逆序對,之前用樹狀數組寫過,此解使用歸並排序的方法求解。
不斷對原數組進行二分,即先求解原數組左邊數組和右邊數組的逆序對數。
當對數組合並時,尋找左邊數組比右邊數組值大的數,優先處理左邊數組,即Left[i] <= Right[j]。
當兩值相等時不滿足逆序對,所以優先將左邊數組相等之加入原數組,
同時累計sum += j-1。
代碼:
#include <bits/stdc++.h> using namespace std; const int MAXN = 1000000+10; int Left[MAXN/2],Right[MAXN/2],a[MAXN]; int n; long long sum = 0; void Megre(int p,int q,int r) { int w; for (int i = p,w = 1;i<=q;i++) Left[w++] = a[i]; for (int i = q+1,w = 1;i<=r;i++) Right[w++] = a[i]; int i = 1,j = 1; w = p; while (w <= r) { if (j > r-q || i <= q-p+1&&Left[i] <= Right[j])//當兩值相等時優先處理左邊數組 { a[w] = Left[i]; i++; sum += j-1;//右邊數組往後移動位數即右邊比左邊當前位置值小的值個數 } else { a[w] = Right[j]; j++; //sum += i-1; } w++; } } void Megre_sort(int p,int r) { if (p < r) { int q = (p + r) / 2; Megre_sort(p, q); Megre_sort(q + 1, r); Megre(p, q, r); /* cout << p << ‘ ‘ << r << ‘:‘ << endl; cout << sum << endl; */ } } int main() { int t; cin >> t; while (t--) { cin >> n; for (int i = 1;i<=n;i++) cin >> a[i]; sum = 0; Megre_sort(1,n); cout << sum << endl; } return 0; }
AKOJ-2021-逆序對(歸並,二分)