AcWing 788. 逆序對的數量

Chemin Du Retour發表於2020-11-14

題目

給定一個長度為n的整數數列,請你計算數列中的逆序對的數量。

逆序對的定義如下:對於數列的第 i 個和第 j 個元素,如果滿足 i < j 且 a[i] > a[j],則其為一個逆序對;否則不是。

輸入格式

第一行包含整數n,表示數列的長度。

第二行包含 n 個整數,表示整個數列。

輸出格式

輸出一個整數,表示逆序對的個數。

資料範圍

1 <= n <= 100000

輸入樣例:

6
2 3 4 5 6 1

輸出樣例:

5

題解

利用歸併排序的時候,兩段區間已經分別排好序,那麼在合併的時候,當有兩個數字時逆序對時,可以發現,大的那個數字的後面那個區間的數字都是大於小的那個數的,所以直接加上 mid - i + 1j即可,所以寫一個歸併排序,在排序的時候順便把數量計算了

int n,a[MAXN],tmp[MAXN]; 
ll ans;

//求區間裡的逆序對數量 
ll merge_sort(int l,int r){
	if(l >= r)return 0;
	int mid = l + r >> 1;
	ll res = merge_sort(l,mid) + merge_sort(mid+1,r);
	
	int k=0,i=l,j=mid+1;
	while(i <= mid && j <= r){
		if(a[i] <= a[j]){   //把小的放進臨時陣列中 
			tmp[k++] = a[i++];
		}
		else{
			tmp[k++] = a[j++];
			res += mid - i + 1;
		}
	}
	
	while(i <= mid)tmp[k++] = a[i++];
	while(j <= r)tmp[k++] = a[j++];
	
	for(int i=l,j=0;i<=r;i++){
		a[i] = tmp[j++];
	}
	return res; 
}

//歸併排序 
int main(){
	cin >> n;
	ans = 0;
	for(int i=0;i<n;i++){
		cin >> a[i];
	}
	ans = merge_sort(0,n-1) ;
	cout << ans << endl;
	
	return 0;
}

相關文章