1. 程式人生 > >【基礎】1019 逆序數

【基礎】1019 逆序數

一個一個比,資料太大就會超時。程式碼如下:

#include<iostream>
using namespace std;
int a[50005];
int main(){
	int n;
	long long ans=0;
	cin>>n;
	for(int i=0;i<n;i++)
		cin>>a[i];
	for(int i=0;i<n-1;i++)
		for(int j=i+1;j<n;j++)
			if(a[i]>a[j])
				ans++;

	cout<<ans<<endl;
	return 0;
} 

利用歸併排序,程式碼如下:

#include<iostream>
#include<algorithm>
using namespace std;
const int n=50005;
int arr[n],brr[n];// arr為原陣列,brr為臨時陣列,n為個人定義的長度
long merge(int low,int mid,int high)
{
	int i=low,j=mid+1,k=low;
	long count=0;
	while(i<=mid&&j<=high)
		if(arr[i]<=arr[j])// 此處為穩定排序的關鍵,不能用小於
			brr[k++]=arr[i++];
		else
		{
			brr[k++]=arr[j++];
			count+=j-k;// 每當後段的陣列元素提前時,記錄提前的距離 
		}
	while(i<=mid)
		brr[k++]=arr[i++];
	while(j<=high)
		brr[k++]=arr[j++];
	for(i=low;i<=high;i++)// 寫回原陣列
		arr[i]=brr[i];
	
	return count;
}
long mergeSort(int a,int b)// 下標,例如陣列int arr[5],全部排序的呼叫為mergeSort(0,4)
{
	if(a<b)
	{
		int mid=(a+b)/2;
		long count=0;
		count+=mergeSort(a,mid);
		count+=mergeSort(mid+1,b);
		count+=merge(a,mid,b);	
		return count;
	}
	return 0;
}
int main(){ 
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
		cin>>arr[i];
	cout<<mergeSort(0,n-1)<<endl;
	return 0;
}

最難理解的是: count+=j-k;// 每當後段的陣列元素提前時,記錄提前的距離

拿陣列 陣列 2 4 3 1 遞迴【分】

注意:每層遞迴arr的值會變,左右兩邊按照從小到大排序。

  2   4   |   1   3

2       4 | 3       1

可以這樣理解:

陣列:2431

第一次1前移1位,2413

第二次1前移2位,1243

第三次3前移1位,1234

把提前的距離相加,得到逆序數。