poj2299

題目大意:給出n個數字,在只能兩兩交換的情況下,要經過多少次才能得到

                  遞增序列


思路:首先,明確的一點是

                     一個數組的逆序數=兩兩交換的情況下得到遞增序列的交換次數

                 舉例如下:

                             一組數列  9,1,0,5,4

                     9 的逆序數是0

                     1 的逆序數是1

                     5 的逆序數是1

                     4 的逆序數是2

                   得到 0+1+1+2=5 恰好等於冒泡排序得到的結果

    

           其次必須瞭解相關的歸併排序的含義:

                  歸併排序是將給出的數組,利用二分法不斷二分化,然後再進行合併排序的方法。

                 利用二分法求逆序數快捷方便。


以下是代碼:

#include <queue>
#include <stack>
#include <math.h>
#include <vector>
#include <limits.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <functional>
using namespace std;
#define inf 1000000000  //10E
#define N 500050    //數組大小
__int64 t;          //定義此類型  足以存放  
void compute(int* s,int top,int mid,int end)            //合併函數
{
     int le=mid+1-top,ri=end-mid;
     int left[N/2],right[N/2];
     int i,j;
     for(i=1;i<=le;i++)
          left[i]=s[top+i-1];
     for(j=1;j<=ri;j++)
          right[j]=s[mid+j];
     left[le+1]=right[ri+1]=inf;
     i=j=1;
     for(int k=top;k<=end;)                //進行合併
     {
          if(left[i]<=right[j])
               s[k++]=left[i++];
          else
          {
               s[k++]=right[j++];
               t+=le+1-i;                 //計算逆序數
          }
     }
     return ;
}
void mergesort(int* s,int top,int end)            //二分
{
    if(top<end)
    {
         int mid=(top+end)/2;
         mergesort(s,top,mid);
         mergesort(s,mid+1,end);
         compute(s,top,mid,end);
    }
    return ;
}

int main()
{
    int n,i;
    int* data=new int[N];
    while(scanf("%d",&n)&&n)
    {
         t=0;
         for(i=1;i<=n;i++)
            scanf("%d",&data[i]);
         mergesort(data,1,n);
         printf("%I64d\n",t);
    }
    delete data;
    return 0;
}

值得注意的是    在c++中傳輸指針的時候 ,必須將數組定義成指針的形式,並且在使用

                  之後刪除。否則,會造成直接傳輸指針錯誤,直接結束程序。











發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章