洛谷 P1908 逆序对

传送门

下面是传送门!

I'm here!


思路

我们可以用树状数组实现

离散化一下,直接将输入的数变为负数,在之后按价值从小到大排序,排完序之后再用树状数组维护,并每次把这个数的位置加入到树状数组中

因为是排完序之后,所以之前加入的一定比后加入的大,然后在查询当前这个数前面位置的数(是前面位置的数,要当前这个数减1),就是逆序对的个数了


代码

#include<bits/stdc++.h>
#define N 500110
#define lowbit(i)  i&-i
using namespace std;

int n,a[N],b[N],t[N];
long long ans=0;

inline int read(){
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
    for(;isdigit(c);c=getchar())x=x*10+c-48;
    return x*f;
}

inline void insert(int x){
    for(int i=x;i<=n;i+=lowbit(i)){
        t[i]++;
    }
}

inline int find(int x){
    int ans=0;
    for(int i=x;i;i-=lowbit(i)){
        ans+=t[i];
    }
    return ans;
}

int main(){
    n=read();
    for(int i=1;i<=n;i++)a[i]=b[i]=-read();
    sort(b+1,b+1+n);
    for(int i=1;i<=n;i++){
        a[i]=lower_bound(b+1,b+n+1,a[i])-b;
    }
    for(int i=1;i<=n;i++){
        ans+=find(a[i]-1);
        insert(a[i]);
    }
    cout<<ans<<'
';
    return 0;
}
我不是天生的王者 但我骨子里流动着不让我低头的血液
原文地址:https://www.cnblogs.com/Snowindira/p/10832183.html