逆序對問題(分治法,歸併排序)

題目鏈接:https://www.luogu.com.cn/problem/P1908

題目描述

對於給定的一段正整數序列,求其中逆序對的數目。逆序對就是序列中 ai>aj且i<j的有序對。
在這裏插入圖片描述

分析

暴力法時間複雜度O(n2),數據規模大時不能AC。需要尋求一種分發高效的算法。考慮到逆序對也是一種有序對,可以採取一種邊排序邊計算的方法。歸併排序是可以解決這個問題的。

#include<cstdio>
int a[500005],b[500005],n;
long long ans;			//數據比較大,得用long long類型,防止溢出 
void mergeSort(int left,int right){
	if(left==right) return;
	int mid=(left+right)/2;
	mergeSort(left,mid);		//遞歸算法 
	mergeSort(mid+1,right);
	int i=left,j=mid+1,k=left;
	while(i<=mid&&j<=right){
		if(a[i]<=a[j]) b[k++]=a[i++];
		else{
			b[k++]=a[j++];
			ans+=mid-i+1;	//累計 
		} 
	}
	while(i<=mid) b[k++]=a[i++];
	while(j<=right) b[k++]=a[j++];
	for(int i=left;i<=right;i++) a[i]=b[i];   //排序之後b[]賦值給a[] 
}
int main() {
	scanf("%d",&n);
	for(int i=0;i<n;i++) scanf("%d",&a[i]);
	mergeSort(0,n-1);
	printf("%lld",ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章