归并和逆序对

逆序对: 对于一个数组a,若i<j,且a[i]>a[j],则称a[i]与a[j]构成逆序对;

归并排序:
划分问题:把序列尽量分成二个相等的二部分
递归求解:把二半元素分别排序
合并问题:把二个有序表合成一个表

求逆序对:由于合并操作是从小到大进行的,当右边一段复制到b数组里面时,左边还没有来得及复制到b数组
的哪些数就是比a[j]大的数,答案加上(r1-l1+1)即可,即;就是把归并排序模板判断(a[l1]<a[l2])(注意等号)加上ans+=r1-l1+1;

代码:

#include<stdio.h>
int a[500005],b[500005];
long long ans;
void mergesort(int l,int r)
{
	if(l>=r)return ;
	int mid=(l+r)/2;//划分 
	mergesort(l,mid);//递归求解 
	mergesort(mid+1,r);//递归求解 
	int l1=l,r1=mid,l2=mid+1,r2=r;
	int tot=0;
	while(l1<=r1&&l2<=r2)//合并 
	{
		if(a[l1]<=a[l2])b[++tot]=a[l1++];
		else b[++tot]=a[l2++],ans+=r1-l1+1;
	}
	while(l1<=r1)b[++tot]=a[l1++];//这二种情况只会 
	while(l2<=r2)b[++tot]=a[l2++];//出现1种情况,想想为什么 
	for(int i=tot,j=r2;i>=1;--i,--j)//将辅助空间b数组复制到a数组 
		a[j]=b[i];
}
int main()
{
	int n;
	while(scanf("%d",&n)&&n)
	{
		ans=0;//注意更新 
		for(int i=1;i<=n;++i)scanf("%d",&a[i]);
		mergesort(1,n);
		printf("%lld\n",ans);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值