前置芝士
引入
逆序对就是序列中 a i > a j a_i>a_j ai>aj 且 i < j i<j i<j 的有序对,求一段正整数序列中逆序对的数目
比较容易想到使用归并排序解决,不过我们这次要用树状数组来解决。
树状数组解决逆序对
显然,以 a i a_i ai为右端的逆序对数量即为 [ 1 , i − 1 ] [1,i-1] [1,i−1]中大于 a i a_i ai的数的个数。我们用类似桶的思路来考虑:每次把 a i a_i ai存入,就统计已存入的数中大于 a i a_i ai的数的个数。使用树状数组维护。
注意到:
序列中每个数字不超过 1 0 9 10^9 109
需要离散化。
#include<iostream>
#include<cstdio>
#include<algorithm>
#define MAXN 500010
using namespace std;
int n,tot;
long long ans;
int a[MAXN];
int p[MAXN];
long long c[MAXN];
int lowbit(int x)
{
return x&-x;
}
void update(int x,int k)
{
for(;x<=tot;x+=lowbit(x))
c[x]+=k;
}
long long query(int x)
{
long long ans=0;
for(;x>=1;x-=lowbit(x))
ans+=c[x];
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
p[i]=a[i];
}
sort(p+1,p+n+1);
tot=unique(p+1,p+n+1)-p-1;
for(int i=1;i<=n;i++)
a[i]=lower_bound(p+1,p+tot+1,a[i])-p;
for(int i=1;i<=n;i++)
{
update(a[i],1);
ans+=query(tot)-query(a[i]);
}
printf("%lld",ans);
return 0;
}