題目大意:給出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++中傳輸指針的時候 ,必須將數組定義成指針的形式,並且在使用
之後刪除。否則,會造成直接傳輸指針錯誤,直接結束程序。