树状数组 模板3 求逆序对(非离散化)

离散化的树状数组:https://blog.csdn.net/A_Pathfinder/article/details/88042960

这里就提一下和普通树状数组的区别,这里是用要查询的数当作下标,而普通树状数组是直接顺序下标放值,也就是说区别在于
updata函数,普通的是updata(i,k);//这里的i就单纯是区间下标;而求逆序对的时候是updata(a[i],1)。我们每次都是在这个数字大小的位置上添加1,然后去更新树状数组,在计算逆序数的时候,只需要查看一下比这个数小或等于的数有多少个,然后现在的位数减去前面比它小的就是所得这一位的逆序数。所有如果要判断的值过大,就要离散处理了。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000000;
int c[maxn];
int n;
int lowbit(int x){
	return x&(-x);
}
void updata(int pos,int k){
	for(int i=pos;i<=n;i+=lowbit(i))
	c[i]+=k; 
}
int getsum(int x){
	int ans=0;
    for(int i=x;i;i-=lowbit(i)){
		ans+=c[i];
	}
	return ans;
}
int main(){
	int nx=0,a;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
	scanf("%d",&a);
	updata(a,1);
	nx+=(i-getsum(a));//用他在的位置减去比他小的个数,就是前面比他大的个数
	}
	cout<<nx;
	return 0;
} 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值