标签:str text 输出 一个 答案 lld cst 快速 print
hihocoder-1524-逆序对
给定一个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; }
标签:str text 输出 一个 答案 lld cst 快速 print
原文地址:http://www.cnblogs.com/zhang-yd/p/7383814.html