逆序对问题(分治法,归并排序)

题目链接: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;
}
发布了136 篇原创文章 · 获赞 12 · 访问量 6082

猜你喜欢

转载自blog.csdn.net/weixin_43590232/article/details/104834129