归并排序——求逆序对

http://bigbang.openjudge.cn
归并——求逆序对数量
首先,逆序对数量cnt应该定义为long long类型
另外,输入输出最好使用printf和scanf,因为速度比cin、cout更快;使用cin、cout在洛谷上能够通过,但是在bigbang上面就不能通过,明明bigbang的数据量更小(bigbang上面n<=350000,洛谷上n<=500000),说明bigbang对时间卡得更严格。

#include<iostream>
#include<cstdio>

using namespace std;
long long cnt=0,n;
int a[550005];//保存元素的数组
int c[550005];//移动元素的数组,用来暂存有序的数组
void Merge(int* a,int left,int mid,int right,int* c){//归并两个序列
	if(a[mid]>a[mid+1]){//如果有逆序才需要移动 
		int l=left,r=mid+1,m=mid;
		int k=left;//注意是从left开始放的! 此题为递归,排序的范围是left~right,不是0~right
		while(l<=mid&&r<=right){
			if(a[l]<=a[r]){//小 大 =》符合条件的序列 ,直接把小的移动到c数组即可
				c[k++]=a[l++]; 
			}
			else { //大 小 => 不符合条件的序列 ,把小的移动到c数组,并且统计逆序对数量
				cnt+=mid-l+1;//从l到mid的数都是a[r]的 逆序对 
				c[k++]=a[r++];
			}
		}
		while(l<=mid){//剩下的元素都是正确的序列了
			c[k++]=a[l++];
		}
		while(r<=right){
			c[k++]=a[r++];
		}
		//c中现在是有序的了,全部复制到a中,(因为排序是在a数组中进行的) 
		for(int i=left;i<=right;i++){
			a[i]=c[i];
		}
	} 
	
}
void Merge_sort(int* a,int left,int right,int* c){
	if(left<right){//归并排序
		int mid=(left+right)/2;
		Merge_sort(a,left,mid,c);//对前半部分排序
		Merge_sort(a,mid+1,right,c);//对后半部分排序
		Merge(a,left,mid,right,c);//将两部分合起来
	}
} 

int main()
{
	scanf("%lld",&n);
	for(int i=0;i<n;i++){
		//cin>>a[i];//使用cin,cout很可能会超时
		scanf("%d",&a[i]);
	}
	int len=n;
	Merge_sort(a,0,len-1,c);
	for(int i=0;i<n;i++){
		printf("%d ",a[i]);
	}
	printf("\n%lld",cnt);
	return 0;
}

一个图片,序列6 5 4 3 2进行归并排序的过程 在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值