CF1201C题解

题目传送门

思路:

这道题要求中位数最大,我们一个一个去试肯定会TLE的,所以我们就要用到一些贪心思想。

贪心:

先看一组数据:

1 1 1000 999 1000

中位数:999

我们可以发现,虽然1很小,但是由于其他的数很大,大的数有三个,小的数有两个,那两个数对中位数没用影响,所以为了让中位数最大,我们要将前一半比较大的数加到很大,不用管后一半较小的数。

再看看怎么加更合适:

再看一组数据:

5 4

1 2 4 6 7

最大中位数:7

我们将4加到7,将6加到7,所以我们发现要想让中位数最大,就要让前一半的数尽可能的接近。

我们已经有了思路,但是一个一个去试中位数的大小,看看是否可以,那么时间复杂度是

O(n^{^2}),也会超时,这里我们就要用二分了。

二分:

二分模板:

int l=1,r=2000000000,mid;
while(l<=r){
	mid=((long long)l+r)/2;
	if(check(mid))l=mid+1;
	else r=mid-1;
}cout<<r;

check函数:

我们可以从中间开始遍历一遍数组,用ans统计一共加了多少数,如果a[i]<mid,那么就让ans减伤它与mid的差,否则就break(我们已经排好了序,后面的只会大于等于mid),最后判断一下ans是否大于k即可。

bool check(int mid){
	int pos=n/2+1;
	long long cnt=0;
	for(int i=pos;i<=n;i++){
		if(a[i]>=mid)break;
		cnt+=(mid-a[i]);
	}if(cnt<=k)return true;return false;
}

完整代码:

#include<iostream>
#include<algorithm>
using namespace std;
int n,k,a[201000];
bool check(int mid){
	int pos=n/2+1;
	long long cnt=0;
	for(int i=pos;i<=n;i++){
		if(a[i]>=mid)break;
		cnt+=(mid-a[i]);
	}if(cnt<=k)return true;return false;
}
int main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++)cin>>a[i];
	sort(a+1,a+1+n);
	int l=1,r=2000000000,mid;
	while(l<=r){
		mid=((long long)l+r)/2;
		if(check(mid))l=mid+1;
		else r=mid-1;
	}cout<<r;
	return 0;
}

AC记录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值