用树状数组求逆序对的时候注意:要统计b[i]-1的前缀和,因为可能有相同值的元素
不去重离散化:
sort(a+1, a+n+1, cmp);
for(int i=1; i<=n; i++) {
if(i == 1 || a[i].val != a[i-1].val) {
tot++;
}
b[a[i].ord] = tot;
}
去重离散化,和不去重差不多,只不过是放到一个新数组里面,并且维护去重后有多少个元素,然后对新数组按输入顺序再排个序就可以了
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 500000 + 10;
long long n,tree[MAXN],ans,tot,b[MAXN];
struct node{
long long ord,val;
}a[MAXN];
void add(long long p, long long x) {
while(p <= n) {
tree[p] += x;
p += (p&-p);
}
}
int getsum(long long p) {
long long sum = 0;
while(p) {
sum += tree[p];
p -= (p&-p);
}
return sum;
}
bool cmp(node x, node y) {
return x.val < y.val;
}
int main() {
scanf("%lld", &n);
for(int i=1; i<=n; i++) {
scanf("%lld", &a[i].val);
a[i].ord = i;
}
sort(a+1, a+n+1, cmp);
for(int i=1; i<=n; i++) {
if(i == 1 || a[i].val != a[i-1].val) {
tot++;
}
b[a[i].ord] = tot;
}
for(int i=1; i<=n; i++) {
ans += i - 1 - getsum(b[i]);
add(b[i], 1);
}
printf("%lld", ans);
return 0;
}