逆序对(归并+树状数组)

使用归并排序求解

对于ans += mid-ii+1 的理解:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 5e5+50;
int a[maxn],tmp[maxn];
ll ans=0;
void merge(int l,int mid,int r)
{
	int cn = l;
	int ii = l,jj = mid+1;
	while( ii<=mid && jj<=r )
	{
		if(a[ii]>a[jj])		//这里可以不一样 
		{
			tmp[cn++] = a[jj++];
			ans += mid-ii+1;
		}
		else
		{
			tmp[cn++] = a[ii++];
		}
	}
	while(ii<=mid) tmp[cn++] = a[ii++];
	while(jj<=r) tmp[cn++] = a[jj++];
	
	for(int i=l;i<=r;i++) a[i] = tmp[i];
}
void msort(int l,int r)
{
	if(l<r)
	{
		int mid = (l+r)/2;
		msort(l,mid);
		msort(mid+1,r);
		merge(l,mid,r);
	}
}
int main()
{
	int n;scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",a+i);
	msort(1,n);
	//for(int i=1;i<=n;i++) cout<<bok[i]<<" ";
	printf("%lld",ans);
	return 0;
}
// 0 1 2 0 3 5

使用离散化+树状数组求解

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 5e5+50;
struct node{
	int val,id;
}a[maxn];
int num[maxn];	// 相对大小数组(离散化后) 
int c[maxn];	
int n;
void add(int p,int x)
{
	while(p<=n) c[p]+=x,p+=(p&-p);
}
int ask(int p)
{
	int res = 0;
	while(p) res+=c[p],p-=(p&-p);
	return res;
}
int cmp(node a,node b)
{
	if(a.val==b.val)
		return a.id<b.id;
	else
		return a.val<b.val;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i].val),a[i].id=i;
	sort(a+1,a+n+1,cmp);
	for(int i=1;i<=n;i++) num[a[i].id] = i;
	ll ans = 0;
	for(int i=1;i<=n;i++)
	{
		add(num[i],1);
		ans += i-ask(num[i]);
	}
	cout<<ans;
	return 0;
}
// 0 1 2 0 3 5

posted @ 2020-06-26 11:04  特立独行的猪猪  阅读(109)  评论(0编辑  收藏  举报