您的位置:首页 > 产品设计 > UI/UE

poj 2299 Ultra-QuickSort

2014-04-29 16:42 316 查看
Ultra-QuickSort

Time Limit: 7000MSMemory Limit: 65536K
Total Submissions: 38588Accepted: 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
;
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;
}


归并排序代码速度更快 391MS

</pre><pre name="code" class="cpp">#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
#define N 500005
#define ll __int64
int a
,b
;
ll ans;
void fun(int l,int r)
{
if(r-l<=1)
return ;
int mid=(l+r)>>1,i,j,k;
fun(l,mid);
fun(mid,r);
k=i=l;
j=mid;
while(i<mid&&j<r)
{
if(a[i]<a[j]||j==r)
b[k++]=a[i++];
else
{
b[k++]=a[j++];
ans+=mid-i;
}
}
while(i<mid)
b[k++]=a[i++];
while(j<r)
b[k++]=a[j++];
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]);
ans=0;
fun(0,n);
printf("%I64d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: