树状数组–求逆序对数
借助树状数组的前缀和 来表示出有多少个数比待处理数小。
所处位置的下标减去它前面小于等于它的个数,就求得它前面有多少个比它大的数的个数
例: 5
4 2 3 1 5
更新一个数,处理一个,ans=0;
第一步:4
ans=0;
第二步:4 2
待处理数:2
已出现的数 (2之前的) 小于等于2的个数:1 (这里是借助树状数组实现)
ans=0+ (2-1)=1;
第三步:4 2 3
待处理数:3
已出现的数小于等于3的个数:2
ans=1+ (3-2) = 2 (实际是减去了一组(2,3) 的情况)
第四步:4 2 3 1
待处理数:1
已出现的数小于等于1的个数:1
ans=2+ (4-1) = 5 ;
第五步:4 2 3 1 5
待处理数:5
已出现的数小于等于5的个数:5
ans=5+ (5-5) = 5 ;
逆序对数:5
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxx=100019;
int n,c[maxx];
int lowbit(int i)
{
return i&(-i);
}
void update(int i,int x)
{
while(i<=n) //注意这里适用于n个数为1-n的情况,否则要改成一个比较大的数
{
c[i]+=x;
i+=lowbit(i);
}
}
int query(int i)
{
int ans=0;
while(i>0)
{
ans+=c[i];
i-=lowbit(i);
}
return ans;
}
int main()
{
int sum=0,x;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%d",&x);
update(x,1);// 说明 x 这个值出现了一次,可能出现很多次,累加
/*
相当于开一个数组,下标为x的位置加1,
query(x)的时候,x前面的都是比x出现的早且小于x的;i-query(x)就是前面有多少比它大的
*/
sum+=i-query(x);
}
printf("%d\n",sum);
}