树状数组求逆序对

首先,由于逆序对只考虑相对大小。可以离散化一下数组。
不妨设 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;
}
posted @ 2017-08-20 21:02  rsqppp  阅读(92)  评论(0)    收藏  举报