[poj 2299]Ultra-QuickSort(离散化+逆序对)


本文最后更新于:2017年9月3日 上午

题目大意

给定若干个未排序的序列,利用冒泡排序原理(交换两个相邻序列元素),求将它们各自变成升序的最小操作数,对于每一个序列输出一个答案。

思路:

其实还是求逆序对个数,但数的范围比较大( $1 \leq x \leq 9999999999$ ),而个数只有$5 \times 10^5$,此时便需要离散化

离散化

STL

const int maxn=6e5+10;
int a[maxn],b[maxn],n,size;
for(int i=1; i<=n; i++)
{
		scanf("%d",&a[i]);
		b[i]=a[i];
}
sort(a+1,a+n+1);
size=unique(a+1,a+n+1)-a-1;
for(int i=1; i<=n; i++)
{
	b[i]=upper_bound(a+1,a+n+1,b[i])-a-1;
	//size=max(b[i],size);
}

手%

const int maxn=6e5+10;
int a[maxn],b[maxn],f[maxn],fu[maxn],n,ma=0;
for(int i=1; i<=n; i++)
{
	scanf("%d",&a[i]);
	b[i]=a[i];
}
sort(a+1,a+n+1);
int cnt=0;
fu[++cnt]=a[1];
for(int i=2; i<=n; i++) if(a[i]!=a[i-1]) fu[++cnt]=a[i];
ma=0;
for(int i=1; i<=n; i++)
{
	f[i]=bs(b[i],1,cnt);
	ma=max(ma,f[i]);
}
int bs(int val,int l,int r)
{
	int m;
	while(l<r)
	{
		m=(l+r)>>1;
		if(fu[m]>=val) r=m;// >= !! 
		else l=m+1;
	}
	return l;
}

Code(BIT):

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define lowbit(x) ((x)&(-(x)))
#define cls(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=6e5+10;
typedef long long ll;
ll sum[maxn];
int a[maxn],b[maxn],n,size;
void update(int,int);
ll query(int);
ll getsum(int,int);
int main()
{
//	freopen("data1.in","r",stdin);
	while(~scanf("%d",&n)&&n)
	{
		cls(sum,0),cls(a,0),cls(b,0),size=0;
		for(int i=1; i<=n; i++)
		{
			scanf("%d",&a[i]);
			b[i]=a[i];
		}
		sort(a+1,a+n+1);
	//	size=unique(a+1,a+n+1)-a-1;
		for(int i=1; i<=n; i++)
		{
			b[i]=upper_bound(a+1,a+n+1,b[i])-a-1;
			size=max(b[i],size);
		}
		ll ans=0;
		cls(sum,0);
		for(int i=1; i<=n; i++)
		{
			ans+=getsum(b[i]+1,size);
			update(b[i],1);
		}
		printf("%lld\n",ans);
	}
	return 0;
}
void update(int p,int val)
{
	for(int i=p; i<=size; i+=lowbit(i))
	{
		sum[i]+=val;
	}
}
ll query(int p)
{
	ll ret=0;
	for(int i=p; i>0; i-=lowbit(i))
	{
		ret+=sum[i];
	}
	return ret;
}
ll getsum(int l,int r)
{
	return query(r)-query(l-1);
}

文章作者: SpaceSkyNet
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 SpaceSkyNet !
  目录
评论