题意:求 n 个数的逆序对数。
思路:首先 n 只有 500000,然而数字范围非常大,将输入离散化成 1~500000 范围的数,离散化后的数组为 li[],li[1]为第一个进入数,将 li[i]对应的树状数组更新为 1,判断 1~li[i]间有几个数已进入(有为 1,无为 0,就是 sum),i-sum(li[i])就是逆序对数。
#include<iostream>
#include<cmath>
#include<queue>
#include<cstring>
#include<string>
#include<map>
#include<stack>
#include<set>
#include<cstdio>
#include<algorithm>
using namespace std;
int n;
int a[500005];
int li[500005];
struct node{
int order;
int num;
}N[500005];
bool cmp(node x, node y){
return x.num<y.num;
}
int lowbit(int x){
return x&(-x);
}
void add(int pos , int num){
while(pos <= n){
a[pos] += num;
pos += lowbit(pos);
}
}
int sum(int n){
int sum = 0;
while(n > 0){
sum += a[n];
n -= lowbit(n);
}
return sum;
}
int main(){
//freopen("a.txt", "r", stdin);
while(scanf("%d", &n) != EOF && n){
for(int i = 1; i <= n; i++){
scanf("%d", &N[i].num);
N[i].order = i;
}
sort(N+1, N+n+1, cmp);
for(int i = 1; i <= n; i++)
li[N[i].order] = i;
memset(a, 0, sizeof(a));
long long ans = 0;
for(int i = 1; i <= n; i++){
add(li[i], 1);
ans += i-sum(li[i]);
}
cout << ans << endl;
}
return 0;
}