首页 > 代码库 > poj 2299 Ultra-QuickSort

poj 2299 Ultra-QuickSort

Ultra-QuickSort
Time Limit: 7000MS Memory Limit: 65536K
Total Submissions: 38588 Accepted: 13903

Description

In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence 
9 1 0 5 4 ,

Ultra-QuickSort produces the output 
0 1 4 5 9 .

Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.

Input

The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.

Output

For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.

Sample Input

5
9
1
0
5
4
3
1
2
3
0

Sample Output

6
0


这道题可以用线段树做,也可以用归并排序做。

线段树做法:

把数组  9 1 0 5 4

映射为1 1 1 1 1,

查找最小值0之前的1个数为2,并把0位置的值改为0,数组改变为1 1 0 1 1

再查找次小值1之前1个数为1;并把1位置的值改为0,数组改变为1 0 0 1 1
重复操作,得到结果为2+1+2+1=6;

 线段树   1032MS

#include"stdio.h"
#include"stdlib.h"
#define N 500005
struct st
{
	int x,id;
}b[N];
struct node
{
	int l,r,s;
}f[N*3];
int cmp(const void*a,const void*b)
{
	return (*(struct st*)a).x-(*(struct st*)b).x;
}
void creat(int t,int l,int r)
{
	f[t].l=l;
	f[t].r=r;
	if(l==r)
	{
		f[t].s=1;
		return ;
	}
	int temp=t*2,mid=(l+r)/2;
	creat(temp,l,mid);
	creat(temp+1,mid+1,r);
	f[t].s=f[temp].s+f[temp+1].s;
}
int find(int t,int l,int r)      //查找1到id之间1的个数
{
	if(f[t].l>=l&&f[t].r<=r)
		return f[t].s;
	int temp=t*2,mid=(f[t].l+f[t].r)/2;
	if(mid>=r)
		return find(temp,l,r);
	else if(mid<l)
		return find(temp+1,l,r);
	else 
		return find(temp,l,mid)+find(temp+1,mid+1,r);
}
void update(int t,int y)        //把位置y的值改为0
{
	if(f[t].l==f[t].r)
	{
		f[t].s-=1;
		return ;
	}
	int temp=t*2,mid=(f[t].l+f[t].r)/2;
	if(mid>=y)
		update(temp,y);
	else
		update(temp+1,y);
	f[t].s=f[temp].s+f[temp+1].s;
}
int main()
{
	int i,n;
	__int64 sum;
	while(scanf("%d",&n),n)
	{
		for(i=1;i<=n;i++)
		{
			scanf("%d",&b[i].x);
			b[i].id=i;
		}
		creat(1,1,n);         // 建树,把各个点都记为1;
		b[0].x=-1;
		qsort(b,n+1,sizeof(b[0]),cmp);
		for(i=1,sum=0;i<=n;i++)
		{
			sum+=find(1,1,b[i].id);
			sum--;
			update(1,b[i].id);
		}
		printf("%I64d\n",sum);
	}
	return 0;
}


二:归并排序做法   2079MS


#include"stdio.h"
#define N 500005
const int inf=(int)1e10;
int a[N];
__int64 sum;
void count(int *a,int l,int mid,int r)
{
	int i,j,k,n1,n2;
	n1=mid-l+1;
	n2=r-mid;
	int *ll=new int [n1+1]; //申请一段大小为n1+1的内存
	int *rr=new int [n2+1];    
	for(k=0;k<n1;k++)
		ll[k]=a[l+k];
	ll[k]=inf;
	for(k=0;k<n2;k++)
		rr[k]=a[mid+1+k];
	rr[k]=inf;
	for(i=j=k=0;k<r-l+1;k++)
	{
		if(ll[i]<=rr[j])
		{
			a[l+k]=ll[i];
			i++;
		}
		else
		{
			a[l+k]=rr[j];
			j++;
			sum+=(n1-i);
		}
	}
	delete ll;       //释放内存空间
	delete rr;
}
void mergesort(int *a,int l,int r)
{                      //归并排序
	if(l<r)
	{
		int mid=(l+r)/2;
		mergesort(a,l,mid);
		mergesort(a,mid+1,r);
		count(a,l,mid,r);     
	}
	return ;
}
int main()
{
	int i,n;
	while(scanf("%d",&n),n)
	{
		for(i=0;i<n;i++)
			scanf("%d",&a[i]);
		sum=0;
		mergesort(a,0,n-1);
		printf("%I64d\n",sum);
	}
	return 0;
}

这个归并排序代码速度更快   360MS

#include"stdio.h"
#define N 500005
int a[N],b[N];
__int64 sum;
void mergesort(int l,int r)    //数组从l到r,不包括右边界
{
	if(r-l<=1)
		return ;
	int mid=(l+r)/2;
	mergesort(l,mid);    //不包括mid
	mergesort(mid,r);      //从mid开始,不含r
	int i=l,j=mid,k=l;
	while(i<mid||j<r)
	{
		if(j>=r||a[i]<=a[j]&&i<mid)
			b[k++]=a[i++];
		else
		{
			b[k++]=a[j++];
			ans+=mid-i;
		}
	}
	for(i=l;i<r;i++)
		a[i]=b[i];
}
int main()
{
	int i,n;
	while(scanf("%d",&n),n)
	{
		for(i=0;i<n;i++)
			scanf("%d",&a[i]);
		sum=0;
		mergesort(0,n);
		printf("%I64d\n",sum);
	}
	return 0;
}