简介

  首先解释一下什么是逆序数,在一个排列中,如果前面的数大于后面的数,则称这两个数为一对逆序,而在这个排列中逆序对的总数称为逆序数。

  然后对于树状数组,如果有一点了解的话,树状数组一般是用于数组区间求和,加单点修改的一种数据结构。如果不了解,可以去百度一下。

思路

  我们要求逆序数,不能直接针对这个排列进行树状数组的添加和求和,这样也没有意义。

  我们需要对于排列中的每一个数是否出现进行树状数组的操作。用一个数组vis,vis[i]=1表示i在这个排列中,为0就表示不存在。

  那我们遍历一遍排列,对于出现的每一个数,我们进行树状数组的添加,加一。表示这个数出现在排列中了。而如果求和的操作,即表示求在当前位置之前比这个数小的数目。

  那i-sum(a)即表示大于这个数的数目,i是当前数的位置,a表示这个数。

代码

  

#include <bits/stdc++.h>
using namespace std;
int num[100005];
int n=100005;
int lowbit(int i){
    return i&-i;
}
void add(int x,int y){
    for(int i=x;i<n;i+=lowbit(i)){
        num[i]+=y;
    }
}
int sum(int x){
    int ans=0;
    while(x>0){
        ans+=num[x];
        x-=lowbit(x);
    }
    return ans;
}
int main()
{
    int m;
    while(cin>>m){
        int a;
        long long ans=0;
        for(int i=1;i<=m;i++){
            cin>>a;
            add(a,1);
            ans+=i-sum(a);
        }
        cout<<ans<<endl;
    }
    return 0;
}

 题目来源:https://ac.nowcoder.com/acm/problem/15163