树状数组求逆序对
首先,由于逆序对只考虑相对大小。可以离散化一下数组。
不妨设 A数组的逆序对是 当有A[j] > A[i] 且j < i的数量.
这样这个逆序对等价于求每个数编号后面比这个数小的数的个数和。
这是一个前缀和操作
区别是,起点是数组的最后个数
结合前面的离散化,这个\(O(n)\)的操作可以通过离散化用树状数组优化成\(O(log(n)\)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2000000;
struct rsqppp{
int data,num;
}S[maxn];
#define lowbit(x) (x&(-x))
int C[maxn];
int n;
void add(int x,int v)
{
while(x <= n)
{
C[x] += v;
x += lowbit(x);
}
}
int query(int x)
{
int ans = 0;
while(x){
ans += C[x];
x-=lowbit(x);
}
return ans;
}
bool A(rsqppp a,rsqppp b)
{
return a.data < b.data;
}
bool B(rsqppp a,rsqppp b)
{
return a.num < b.num;
}
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;i++)
{
scanf("%d",&S[i].data);
S[i].num = i;
}
sort(S+1,S+1+n,A);
int kk = 0;
for(int i = 1;i <= n;i++){
if(S[i].data != S[i-1].data){
S[i].data = ++kk;
}else{
S[i].data = kk;
}
}
sort(S+1,S+1+n,B);
int ans = 0;
for(int i = n;i >= 1;i--){
ans += query(S[i].data);
add(S[i].data,1);
}
printf("%d",ans);
return 0;
}

浙公网安备 33010602011771号