题目大体意思:有n头牛,你需要在其中选c头,使得这c头牛最近的2头牛之间的的距离最远,输出最近的最远距离
我们可以从最大距离和最小距离之间选择一个最大的可实现距离,因为数据过大,无法顺序选择,只有通过二分可以实现:先二分找一个距离,若这个距离可以实现,则用变量替换此数(注意不用比较,因为二分得到的答案一定是更优更大的),就往更大的距离去寻找,若这个距离不可以实现,就往更小的距离去找,重复寻找,直到区域区间之内没数为止。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int A[1000010];
int n,c,a;
bool check(int x)//判断此答案是否可行
{
int num = 0;
int l = A[1];//l记录上一只牛的位置,开始时第一只牛一定在第一个牛栏
for(int i = 2; i <= n;i ++)//依次枚举每个牛栏
{
if(A[i] - l < x) num ++;//若此距离不满足当前答案,那么需要的牛栏数+1,即把当前牛放到下一个牛栏
else l = A[i];//否则就更新上一次的牛栏位置 ,即上一头牛放的位置
if(num > a) return false;// 若需要牛栏数大于最大牛栏数,此答案不可行
}
return true;//反之,若需要牛栏数小于最大需要牛栏数,此答案可行
}
int main()
{
scanf("%d%d",&n,&c);
for(int i = 1;i <= n;i ++)
scanf("%d",&A[i]);
sort(A + 1,A + n + 1);//由于无序,需排序(sort默认从小到大,不用写规则)
a=n-c;//最大剩余牛栏数
int l = 1;//二分的左界,从1开始,即可能情况的最小值
int r = A[n] - A[1];//二分右界,即可能情况的最大值
while( l+1 < r )//若左<右,则继续二分答案
{
int mid = (l + r)/2;//二分 两区间分别为l ~ mid , mid ~ r;
if(check(mid)) l = mid;//若此答案可行,从mid ~ r区间继续查找(更大答案),即修改左界l=mid
else r = mid;//反之,若此答案不可行,从l ~ mid区间查找(合理答案),即修改左界l=mid
}
if(check(r)) printf("%d",r);//若可行解为右界,输出右界
else printf("%d",l);//若可行解为左界,输出左界
return 0;
}