题目链接:
https://www.luogu.com.cn/problem/P1908
题目大意:
给长为 n 的序列,求序列中逆序对的数目
思路:
一、
归并:
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 5e5 + 10;
LL a[N], tmp[N], n, ans = 0;
void mergeSort(LL l, LL r){
if (l >= r) return;
LL mid = (l + r) >> 1, i = l, j = mid + 1, cnt = 0;
mergeSort(l, mid);
mergeSort(mid + 1, r);
while (i <= mid || j <= r)
if (j > r || (i <= mid && a[i] <= a[j]))
tmp[cnt++] = a[i++];
else
tmp[cnt++] = a[j++], ans += mid - i + 1;
for (LL k = 0; k < r - l + 1; k++)
a[l + k] = tmp[k];
}
int main(){
cin >> n;
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
mergeSort(1, n);
cout << ans << "\n";
return 0;
}
二、
树状数组:
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
struct fwt{
int n;
vector <int> a;
fwt(int n) : n(n), a(n + 1) {}
LL sum(int x){
LL res = 0;
for (; x; x -= x & -x)
res += a[x];
return res;
}
void add(int x, LL k){
for (; x <= n; x += x & -x)
a[x] += k;
}
LL query(int x, int y){
return sum(y) - sum(x - 1);
}
};
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i ++ ){
cin >> a[i];
}
auto b = a;
sort(b.begin(), b.end());
b.erase(unique(b.begin(), b.end()), b.end());
for (int i = 0; i < n; i ++ ){
int t = lower_bound(b.begin(), b.end(), a[i]) - b.begin() + 1;
a[i] = t;
}
fwt f(n);
LL ans = 0;
for (int i = n - 1; i >= 0; i -- ){
ans += f.query(1, a[i] - 1);
f.add(a[i], 1);
}
cout << ans << "\n";
return 0;
}