树状数组求逆序对

统计对于每个i<j,求a[i]>a[j]的数量
在每一次更新(update)树状数组时,以元素的值作为树状数组的索引,更新的值为 +1,代表个数。

在每一次获取(query)逆序对数时,存在于树状数组中的元素的索引值都比当前元素的大(逆序遍历),

那么自然获取到的树状数组的值即为索引值比当前元素的大,且值比当前元素的小的个数。

从排列中的最后一个数开始遍历,每次在树状数组中查询有多少个数小于当前的数P[j]

(即用树状数组查询数组A目前P[j]−1个数的前缀和)并加入计数器,之后对树状数组执行修改数组A第P[j]个数值加1的操作。

#include<bits/stdc++.h>

using namespace std;

using ll=long long;
const int N=5e5+5;
int n,rng;
int a[N],org[N];
struct TreeArray{
private:
	ll bitree[N];
public:
	ll lowbit(int x){	
		return x&(-x);
	}
	void update(int pos,int val){
		for(;pos<=rng;pos+=lowbit(pos)) bitree[pos]+=val;
		//注意,下标为离散化后的值域
	}
	ll query(int pos){
		int res=0;
		for(;pos;pos-=lowbit(pos)) res+=bitree[pos];
		return res;
	}
};
TreeArray tree;

int main(){
	cin.tie(nullptr)->sync_with_stdio(false);
	cin>>n;
	for(int i=1;i<=n;++i){
		cin>>a[i];
		org[i]=a[i];//保存原数据
	}
	
	sort(a+1,a+1+n);
	rng=unique(a+1,a+1+n)-a-1;//离散化的步骤,在部分题目中不是必需的
	ll ans=0;
	for(int i=n;i>=1;--i){
		int tmp=lower_bound(a+1,a+1+rng,org[i])-a;//获取排名
		ans+=tree.query(tmp-1);
		tree.update(tmp,1);
	}
	
	cout<<ans<<'\n';
	return 0;
}
posted @ 2025-10-23 21:40  _CENSORED  阅读(3)  评论(0)    收藏  举报