题目描述
陶陶是个贪玩的孩子,他在地上丢了A个瓶盖,为了简化问题,我们可以当作这A个瓶盖丢在一条直线上,现在他想从这些瓶盖里找出B个,使得距离最近的2个距离最大,他想知道,最大可以到多少呢?
输入输出格式
输入格式:
第一行,两个整数,A,B。(B<=A<=100000)
第二行,A个整数,分别为这A个瓶盖坐标。
输出格式:
仅一个整数,为所求答案。
输入输出样例
输入样例#1:
5 3
1 2 3 4 5
输出样例#1:
2
类似的最大值最小化或者最小值最大化问题,通常用二分法就可以很好地解决。我们定义: 设
C(d)表示可以安排瓶盖的位置使得最近的两个瓶盖的距离不小于 d 那么问题就变成了求满足 C(d)的最大的 d,另外,最近的间距不小于 d
也可以说成是所有瓶盖的间距都不小于 d,因此就有 C(d)表示可以安排瓶盖的位置使得任意的两个瓶盖的距离不小于 d。
这个问题的判断使用贪心法便可非常容易地求解。
1.对瓶盖的位置 x 进行排序
2.把第一个瓶盖放入 x0 的位置
3.如果第 i 个瓶盖放入了 xj 的话,第 i+1 个瓶盖就要放入满足 xj+d≤xk 的最小的 xk 中 对 x 的排序只需在最开始时进行一次就可以了,每一次判断对每个瓶盖最多进行一次处理,因此时间复杂度是 O(nlogn) 代码如下:
#include<bits/stdc++.h>
using namespace std;
int a,b,l,r,mid;
int A[1000001];
inline bool check(int x)
{
int s=A[1]+x;
int sum=1;
for(int i=2;i<=a;i++)
{
if(A[i]>=s)
{
sum++;
s=A[i]+x;
}
}
return sum>=b;
}
int main()
{
cin>>a>>b;
for(int i=1;i<=a;i++)
cin>>A[i];
sort(A+1,A+1+a);
l=0;r=A[a]-A[1];
while(l<=r)
{
mid=l+r>>1;
if(check(mid)) l=mid+1;
else r=mid-1;
}
cout<<r;//用l不对
return 0;
}