【原】 POJ 2299 Ultra-QuickSort 逆序数 解题报告

 

http://poj.org/problem?id=2299

 

方法:

利用merge sort求逆序数,复杂度nlgn
如果比较每一对儿数(或使用bubble sort),复杂度为n^2,太慢
对于一对儿逆序对儿,有三种情况:两数都在数组左半边,两数都在数组右半边,两数分别在左右两个半边。
由于Merge时两个半边都为sorted,所以只会出现第三种情况。
计算逆序数只需要在Merge中加一句即可,当a[lb]>a[rb]时,a[lb...le]>a[rb],所以逆序数为(le-lb+1)
由于题目中n<500,000,所以逆序数为O(n^2),需要使用__int64存放,不然会溢出

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 clip_image001

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

 

   1:  
   2: __int64 totalReverse = 0 ;
   3:  
   4: void Merge(int *a,int *tmpArr,int lb,int rb,int re)
   5: {
   6:     int le = rb-1 ;
   7:     int index = lb ;
   8:     int cpback = lb ;
   9:     while( lb<=le && rb<=re )
  10:     {
  11:         if( a[lb] <= a[rb] )
  12:             tmpArr[index++] = a[lb++] ;
  13:         else
  14:         {
  15:             tmpArr[index++] = a[rb++] ;
  16:             totalReverse += (le-lb+1) ;  //***  counting the reverse-pairs
  17:         }
  18:     }
  19:  
  20:     //copy the rest to the temp array
  21:     while(lb<=le)
  22:         tmpArr[index++] = a[lb++] ;
  23:     while(rb<=re)
  24:         tmpArr[index++] = a[rb++] ;
  25:  
  26:     //copy back
  27:     for( ; cpback<=re ; ++cpback )
  28:         a[cpback] = tmpArr[cpback] ;
  29: }
  30:  
  31: void Msort(int *a,int *tmpArr,int b,int e)
  32: {
  33:     if(b<e)
  34:     {
  35:         int mid = b+(e-b)/2 ;
  36:         Msort(a,tmpArr,b,mid);
  37:         Msort(a,tmpArr,mid+1,e);
  38:         Merge(a,tmpArr,b,mid+1,e);
  39:     }
  40: }
  41:  
  42: void MergeSort(int *a,int *tmpArr,int n)
  43: {
  44:     Msort(a,tmpArr,0,n-1) ;
  45: }
  46:  
  47: void run2299()
  48: {
  49:     int n ;
  50:     int i;
  51:     int *a = new int[500000];
  52:     int *tmpArr = new int[500000];
  53:     while(cin>>n)
  54:     {
  55:         if(n==0)
  56:              break ;
  57:  
  58:         for(i=0;i<n;++i)
  59:             cin>>a[i] ;
  60:         MergeSort(a,tmpArr,n) ;
  61:         cout<<totalReverse<<endl;
  62:         totalReverse = 0 ;
  63:     }
  64:     delete []a;
  65:     delete []tmpArr;
  66: }

转载于:https://www.cnblogs.com/allensun/archive/2010/11/05/1870216.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值