树状数组--求逆序对数

树状数组–求逆序对数

借助树状数组的前缀和 来表示出有多少个数比待处理数小。
所处位置的下标减去它前面小于等于它的个数,就求得它前面有多少个比它大的数的个数

例: 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);

}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值