树状数组求逆序对
统计对于每个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;
}

浙公网安备 33010602011771号