题目链接:https://cn.vjudge.net/problem/OpenJ_Bailian-2299
求逆序数,可以用树状数组,也可以线段树,不过树状数组更简洁一点
离散化之后,在线查询更新,树状数组求出这个数前面有多少个数比它小(设为temp),然后用应该比它小的数减去temp就是在它后面比它小的,就是逆序对的数量
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#define ll long long
const int maxn = 1e6+6;
using namespace std;
struct node {
ll a;
int id;
friend bool operator <(node a,node b){
return a.a<b.a;
}
}pos[maxn];
bool cmp(node a,node b){
return a.id<b.id;
}
ll c[maxn];
int n,m;
ll lowbit(ll a) {
return (-a)&a;
}
void update(ll a) {
while(a<maxn) {
c[a]++;
a+=lowbit(a);
}
}
ll query(ll a) {
ll ans=0;
while(a) {
ans+=c[a];
a-=lowbit(a);
}
return ans;
}
int main()
{
while(scanf("%d",&n)&&n) {
memset(c,0,sizeof(c));
for(int i=0;i<n;i++) {
scanf("%lld",&pos[i].a);
pos[i].id = i;
}
sort(pos,pos+n);
for(int i=0;i<n;i++) {
pos[i].a=i+1;
}
sort(pos,pos+n,cmp);
ll ans=0,temp;
for(int i=0;i<n;i++) {
temp = query(pos[i].a);
ans+=i-temp;
update(pos[i].a);
}
printf("%lld\n",ans);
}
return 0;
}