POJ 2299 Ultra-QuickSort (逆序数)

Ultra-QuickSort
Time Limit: 7000MS Memory Limit: 65536K
Total Submissions: 39468 Accepted: 14221

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
 
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 5000010
__int64 cur=0;
int a[M],temp[M];
void mergesort(int *a, int first, int last, int *temp)  
{  if(first==last) return;
    if(first<last)
	{
    int i= first,p = first;  
    int m = (first+last)/2,   n = last;  
    int q = m + 1;  
    mergesort(a,first,m,temp);
	mergesort(a,m+1,last,temp);
    while (p <= m ||q<= n)  
    {  
        if (p<=m && q<=n && a[p] <= a[q])  
            temp[i++] = a[p++];
		    	
		if(p<=m && q<=n && a[p]>a[q])
		{
			cur+=m+1-p;
            temp[i++] = a[q++];	
		}    
    while (q>n && p<=m)  
        temp[i++] = a[p++]; 
    while(p >m &&q <=n)
	{
		temp[i++]=a[q++];
	}
	}
    for (i = first; i <= n; i++)  	
        a[i] = temp[i];  
	}     
	  
} 
int main()
{ int  n,t,i,j;
	while(scanf("%d",&n)!=EOF&&n!=0)
	{ 
      for(i=0;i<n;i++)
		  scanf("%d",&a[i]);

	    mergesort(a,0,n-1,temp);
/*	for(i=0;i<n;i++)
		printf("%d ",a[i]);
*/
	  printf("%I64d\n",cur);
	  cur=0;
	}
	return 0;
}

超时代码:
#include <iostream>
#include<cstdio>
using namespace std;
#define M 500010
__int64 cur;
int a[M],temp[M];
void mergearray(int a[], int first, int mid, int last, int temp[])  
{  
    int i = first, j = mid + 1;  
    int m = mid,   n = last;  
    int k = 0;  
      
    while (i <= mid && j <= last)  
    {  
        if (a[i] <= a[j])  
            temp[k++] = a[i++];
		    	
		else  
		{
            temp[k++] = a[j++];
			cur+=mid+1-i;
		}  
	} 
      
    while (i <= mid)  
        temp[k++] = a[i++]; 
    while (j <= last)  
        temp[k++] = a[j++];  
    for (i = 0; i < k; i++)  	
        a[first + i] = temp[i];  
}  
void mergesort(int a[], int first, int last, int temp[])  
{  
    if (first < last)  
    {  
        int mid = (first + last) / 2;  
        mergesort(a, first, mid, temp);    //左边有序  
        mergesort(a, mid + 1, last, temp); //右边有序  
        mergearray(a, first, mid, last, temp); //再将二个有序数列合并  
    }  
}  
  
bool MergeSort(int a[], int n)  
{  
    int *p = new int[n];  
    if (p == NULL)  
        return false;  
    mergesort(a, 0, n - 1, p);  
    delete[] p;  
    return true;  
}
  
int main()
{ int  n,t,i,j;
	while(scanf("%d",&n)!=EOF)
	{ cur=0;
      for(i=0;i<n;i++)
		  scanf("%d",&a[i]);
      for(i=0;i<n;i++)
	mergesort(a,0,n-1,temp);
/*	for(i=0;i<n;i++)
		printf("%d ",a[i]);
*/
	  printf("%I64d\n",cur);
	}
	return 0;
}
题目描述:求冒泡排序的交换次数
所用算法:用归并排序,求逆序数的个数
提交情况:1次tle(直接冒泡排序n^2的复杂度,对于5000000的数据量,必然超时),1次wa(统计个数时整数溢出了),1a
心得体会:初看题目很简单,没有往数据量方面想,直接冒泡计数提交,然后看着poj上一直running&&judging直到tle, 时限7000ms呀。没做过逆序数的类似问题,
而且题目本身分类也在排序那,然后考虑是不是能快排一下,比较排序前和排序后各个数的位置。考虑再三,发现解决不了。去论坛上瞄了一眼,看到可以用逆序数
解,于是百度+算法导论,学到了如何用归并排序计算逆序数的数目,写成程序,中间还出现了一次wa,然后就ac了。我在看算法导论时,因为merge在书一开始讲的
,想平时排序都是快排为主流,就没有仔细想过merge可能的变种,这道题充分印证了,即使merge本身可能用的不多,但分冶的思想却是无所不在

感觉两个都一样,只是一个用一个只用了一个函数,一个用了两个函数。
但是一个300+MS,一个超时。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值