hihocoder-1524-逆序對
阿新 • • 發佈:2017-08-17
+= swe problem clu merge 0ms bit main d+
hihocoder-1524-逆序對
#1524 : 逆序對
時間限制:10000ms 單點時限:1000ms 內存限制:256MB描述
給定一個1-N的排列A1, A2, ... AN,如果Ai和Aj滿足i < j且Ai > Aj,我們就稱(Ai, Aj)是一個逆序對。
求A1, A2 ... AN中所有逆序對的數目。
輸入
第一行包含一個整數N。
第二行包含N個兩兩不同整數A1, A2, ... AN。(1 <= Ai <= N)
對於60%的數據 1 <= N <= 1000
對於100%的數據 1 <= N <= 100000
輸出
一個整數代表答案
- 樣例輸入
-
5 3 2 4 5 1
- 樣例輸出
-
5
經典的用merge sort 來解決逆序對的問題。
#include <cstdio> const int MAXN = 1e5 + 10; const int MOD = 1000000007; int num[MAXN], tmp[MAXN]; long long cnt; void Merge_Sort(int l, int r){ int mid = l + (r - l)/2; int p = l, p1 = l, p2 = mid + 1; while(p1<=mid && p2<=r){ if(num[p1] > num[p2]){ tmp[p++] = num[p2++]; cnt += (mid - p1 + 1); }else{ tmp[p++] = num[p1++]; } } while(p1<=mid){ tmp[p++] = num[p1++]; } while(p2<=r){ tmp[p++] = num[p2++]; } for(int i=l; i<=r; ++i){ num[i] = tmp[i]; } } void Merge(int l, int r){ if(l >= r ){ return; } int mid = l + (r - l)/2; Merge(l, mid); Merge(mid+1, r); Merge_Sort(l, r); } int main(){ int n; while(scanf("%d", &n) != EOF){ for(int i=0; i<n; ++i){ scanf("%d", &num[i]); } cnt = 0; Merge(0, n-1); printf("%lld\n", cnt ); } return 0; }
方法二,參考了網友的answer,因為 num 的range 是 [1, n] , 所以,可以采用樹狀數組。只需要對 num 一個一個插入到 dp[] 數組中,快速計算 sum即可。
#include <cstdio> #include <cstring> const int MAXN = 1e5 + 10; const int MOD = 1000000007; long long cnt; int n, num[MAXN], dp[MAXN]; int lowbit(int x){ return x & -x; } long long GetSum(int pt){ long long ans = 0; int i = pt; while(i <= n){ ans += dp[i]; i += lowbit(i); } return ans; } void AddNum(int pt, int v){ int i = pt; while(i > 0){ dp[i] += v; i -= lowbit(i); } } int main(){ freopen("in.txt", "r", stdin); while(scanf("%d", &n) != EOF){ for(int i=0; i<n; ++i){ scanf("%d", &num[i]); } memset(dp, 0, sizeof(dp)); cnt = 0; for(int i=0; i<n; ++i){ cnt += GetSum(num[i]); AddNum(num[i], 1); } printf("%lld\n", cnt ); } return 0; }
hihocoder-1524-逆序對