进击的奶牛(USACO位置年份的比赛) 二分答案

二分答案

二分答案 与二分查找类似,二分查找有一个前提就是数列要求是有序的,二分答案则是要求 满足条件的答案是单调有序的,它的基本思想是在答案可能的范围 ([L,R]) 内二分查找答案,不断检查当前答案是否满足题目的要求,根据检查结果 更新查找的区间,最终取得最符合题目要求的答案进行输出。

答案的单调性:
如何理解答案的单调性呢?可以见下图,该图表示一个区间,从左到右要实现的代价逐渐增高,我们要在这个区间里找到一个代价最小的满足条件的答案。观察图可以发现,位于答案左边的区间不满足条件,位于答案右边的区间满足条件,像这种要么一边不满足,要么一边都满足的现象就是答案的单调性。

题目描述

一个牛棚n个间隔,他们分布在一条直线上,坐标是​ x1,x2,x3…xn。现在需要把c头牛安置某些间隔,使得所有牛中相邻两头的最近距离越大越好,求这个最大的近距离。例如有5个间隔3头牛,间隔的坐标是[1,2,8,4,9]。可以将牛关在[1,4,9]这些间隔中,最近的距离是3。如果要求所有牛之间的距离大于3,是办不到的。

分析

还是按照套路可以构造判断条件把c头牛全部安置进这些间隔使相邻两头牛的距离不超过x。于是得先检验单调性:可以看出x越小就越有可能把所有的牛安置;当x比较大时牛棚就不够安置了。于是不难想象存在一个分界线ans,x大于ans时没有合法安置方案。要找到这个ans作为答案。图片所示为间距条件的成立关系。

画的有点歪,大致明白就行
标题画的有点歪,大致明白就行


那么问题变为如何在优秀复杂度下检验“条件”的正确性。只有一个限制,及任意两个相邻安置点距离不能小于x。于是可以大致感受到一种贪心算法:从最左端开始,每个隔超过了x的距离,能安置就安置,可以证明安置一定比不安置更优。最后只要看遍历所有点以后共安置了多少头牛即可。代码如下

#include<bits/stdc++.h>
#define N 1000010
#define M 1e9
using namespace std;
int a[N],n,c;
bool p(int d)
{
	int k=0,last=-M;//last用来记录上一头牛的坐标。
	for(int i=1;i<=n;i++)
		if(a[i]-last>=d)//能安置就立刻安置。
			last=a[i],k++;
			return k>=c;
}
int main()
{
	cin>>n>>c;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	sort(a+1,a+1+n);
	int l=0,r=M,ans,mid;
	while(l<=r)
		if(p(mid=l+r>>1))
			ans=mid,l=mid+1;
		else
			r=mid-1;
		cout<<ans;
		return 0;
}

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值