逆序对_树状数组

b[i]为原数组,表示当前数i出现次数

用树状数组c[i]维护前i个b[i]的和,即当前<=i的数的个数

只要依次扫插入并统计数a[i]之前比a[i]大的数的个数即可求得逆序对

需要离散化

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <set>
#define ll long long
using namespace std;
const int MAXN=5e5+10;
int n;
ll ans;
int a[MAXN],x[MAXN],c[MAXN];
inline int in()
{
	int x=0,flag=1;
	char ch=getchar();
	while (ch<'0'||ch>'9') {if (ch=='-') flag=-1;ch=getchar();}
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x*flag;
}
bool cmp(int x,int y)
{
	return a[x]<a[y];
}
int lowbit(int x) {return x&(-x);}
int query(int x)
{
	int cnt=0;
	while (x)
	{
		cnt+=c[x];
		x-=lowbit(x);
	}
	return cnt;
}
void updata(int x,int val)
{
	while (x<=n)
	{
		c[x]+=val;
		x+=lowbit(x);
	}
}
int main()
{
	n=in();
	for (int i=1;i<=n;i++) a[i]=in(),x[i]=i;
	sort(x+1,x+n+1,cmp); 
	for (int i=1;i<=n;i++) a[x[i]]=i;
	for (int i=1;i<=n;i++)
	{
		//printf("%d ",query(a[i])); 
		ans+=(ll)(i-1-query(a[i]));
		updata(a[i],1);
	}
	//for (int i=1;i<=n;i++) printf("%d ",a[i]);
	printf("%lld",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/wangyc123456/article/details/80351133