poj 2299 Ultra-QuickSort 归并排…

来源:互联网 发布:java queue 编辑:程序博客网 时间:2024/06/05 11:40
Ultra-QuickSort
Time Limit: 7000MSMemory Limit: 65536KTotal Submissions: 22296Accepted: 7943

Description

poj <wbr>2299 <wbr>Ultra-QuickSort <wbr>归并排序求逆序数In this problem, you have toanalyze a particular sorting algorithm. The algorithm processes asequence of n distinct integers by swapping two adjacent sequenceelements until the sequence is sorted in ascending order. For theinput 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-QuickSortneeds to perform in order to sort a given input sequence.

Input

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

Output

For every input sequence, your program prints asingle line containing an integer number op, the minimum number ofswap operations necessary to sort the given input sequence.

Sample Input

0

Sample Output

0
这题是要求数列的逆序数。所谓数列的逆序数就是一个值sumsum=b[0]+b[1]+...+b[n-1]。这里假设数列为a,其中b[i]表示在数列中在a[i]后面并且比a[i]小的数的个数。比如有数列 2 8 0 3的逆序数就是1+2+0+0=3
求在数列的逆序数可以使用归并排序。归并排序是将数列a[l,h]分成两半a[l,mid]a[mid+1,h]分别进行归并排序,然后再将这两半合并起来。在合并的过程中(设l<=i<=midmid+1<=j<=h),当a[i]<=a[j]时,并不产生逆序数;当a[i]>a[j]时,在前半部分中比a[i]大的数都比a[j]大,将a[j]放在a[i]前面的话,逆序数要加上mid+1-i。因此,可以在归并排序中的合并过程中计算逆序数。
两个代码稍有不同,一个静态申请内存,一个是动态
#include<stdio.h>
#include<malloc.h>
__int64 k=0;
int a[500001];
void Merge(int *R,int low,int m,int high)
    {
     int i=low,j=m+1,p=0;
     int *R1; 
     R1=(int *)malloc((high-low+1)*sizeof(int));   
     while(i<=m&&j<=high) 
         {
              if(R[i]<=R[j])
          {
                      R1[p++]=R[i++];
                    
               }
              else
           {
                       R1[p++]=R[j++];//如果后面的数要前移,说明前半部分的后面的数原先是大于后半部分的那个数的,等于m-i+1,
        //因为每部分数组是有序的。
                        k+=(m-i+1);
            }
      }
     while(i<=m) 
       R1[p++]=R[i++];
     while(j<=high) 
       {
              R1[p++]=R[j++];            
        }
              
     for(p=0,i=low;i<=high;p++,i++)
       R[i]=R1[p];
       free(R1);
    
 void MergeSortDC(int *R,int low,int high)
     {
       int mid;
       if(low<high)
           {
          mid=(low+high)/2;
          MergeSortDC(R,low,mid); 
          MergeSortDC(R,mid+1,high); 
          Merge(R,low,mid,high); 
        }
     }
 int main()
 {
       int i,n;   
       while(scanf("%d",&n)!=EOF)
     {
              k=0;
           if(n==0) break;
                for(i=0;i<n;i++)
                 scanf("%d",&a[i]);
     MergeSortDC(a,0,n-1);       
              printf("%I64d\n",k);
  }
       return 0;
  
 }






#include<stdio.h>
__int64 k=0;
int a[500001],R1[500001];
void Merge(int *R,int low,int m,int high)
    {
     int i=low,j=m+1,p=0;    
     while(i<=m&&j<=high) 
    {
               if(R[i]<=R[j])
           {
                       R1[p++]=R[i++];
                     
                }
               else
            {
                       R1[p++]=R[j++];//如果后面的数要前移,说明前半部分的后面的数原先是大于后半部分的那个数的,等于m-i+1,
        //因为每部分数组是有序的。                    
       k+=(m-i+1);
                }
       }
     while(i<=m) 
       R1[p++]=R[i++];
     while(j<=high) 
        {
               R1[p++]=R[j++];            
         }
               
     for(p=0,i=low;i<=high;p++,i++)
       R[i]=R1[p];
    
 void MergeSortDC(int *R,int low,int high)
     {
       int mid;
       if(low<high)
     {
          mid=(low+high)/2;
          MergeSortDC(R,low,mid); 
          MergeSortDC(R,mid+1,high); 
          Merge(R,low,mid,high); 
        }
     }
 int main()
 {
        int i,n;   
        while(scanf("%d",&n)!=EOF)
      {
               k=0;
            if(n==0) break;
         for(i=0;i<n;i++)
          scanf("%d",&a[i]);
      MergeSortDC(a,0,n-1);       
               printf("%I64d\n",k);
   }
        return 0;
   
 }





原创粉丝点击