hdu 4911 归并排序求逆序对数


前言

下午hdu oj又再次登不上了,终于在晚上又能登上了,来一波归排~


一、题目

伟大的传送门
在这里插入图片描述

二、题目分析

一道以归并排序为板子的题,需讨论以下两种情况(设有cnt个逆序对):
1.cnt<=k,即逆序对的数量不大于最大交换次数k,所以进行了k次交换后,最少的逆序对数为0;
2.cnt>k,让k次交换都发生在逆序的相邻数上,则剩余逆序对数为cnt-k;
此求取逆序对的程序完全套用了归并排序的模板,相比之下多了一个cnt+=mid-i+1;

三、代码

归并排序思想:采用分治法进行排序,将序列分成一个个小序列1,再将排序后的小序列合并成一个较大序列…最终得到排序好的序列。

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
//板子:计算逆序对,即在进行归并排序时判断记录,cnt+=mid-i+1;
const int maxn=100005;
typedef long long ll;
ll a[maxn],b[maxn],cnt;

void Merge(ll l,ll mid,ll r){
	ll i=l,j=mid+1,t=0;//定义i,j两个指针用于归并排序 
	while(i<=mid&&j<=r){
		if(a[i]>a[j]){//前大于后------出现逆序对 
			cnt+=mid-i+1;//计算逆序对个数 
			b[t++]=a[j++];//合并,执行顺序:先b[t]=a[j],后t++,j++; 
		}
		else b[t++]=a[i++];//
	}
	//两个while语句只会执行其中一个或都不执行 
	while(i<=mid) b[t++]=a[i++];//当左边子序列经过上边操作后有剩余,则全复制到b中 
	while(j<=r) b[t++]=a[j++];//同上;
	 
	for(i=0;i<t;i++){//最后将b中元素全返回给a 
		a[l+i]=b[i];
	}
} 

void Mergesort(ll l,ll r){//递归实现归排 
	if(l<r){
		ll mid=(l+r)/2;
		Mergesort(l,mid);//左 
		Mergesort(mid+1,r);//右 
		Merge(l,mid,r);
	}
} 

int main(){
	ll n,k;
	while(cin>>n>>k){
		cnt=0;
		for(ll i=0;i<n;i++)
		cin>>a[i];
		
		Mergesort(0,n-1);
		if(cnt<=k)cout<<"0"<<endl;
		else printf("%I64d\n",cnt-k);
	} 
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值