求逆序数——树状数组
简介
首先解释一下什么是逆序数,在一个排列中,如果前面的数大于后面的数,则称这两个数为一对逆序,而在这个排列中逆序对的总数称为逆序数。
然后对于树状数组,如果有一点了解的话,树状数组一般是用于数组区间求和,加单点修改的一种数据结构。如果不了解,可以去百度一下。
思路
我们要求逆序数,不能直接针对这个排列进行树状数组的添加和求和,这样也没有意义。
我们需要对于排列中的每一个数是否出现进行树状数组的操作。用一个数组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