为了弥补自己的二分太渣,从二分的水题做起,从我做起~
题目描述
农夫约翰建造了一座有n间牛舍的小屋,牛舍排在一条直线上,第i间牛舍在xi的位置,但是约翰的m头牛对小屋很不满意,因此经常互相攻击。约翰为了防止牛之间互相伤害,因此决定把每头牛都放在离其它牛尽可能远的牛舍。也就是要最大化最近的两头牛之间的距离。
牛们并不喜欢这种布局,而且几头牛放在一个隔间里,它们就要发生争斗。为了不让牛互相伤害。John决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是多少呢?
输入
第一行用空格分隔的两个整数n和m;
第二行为n个用空格隔开的整数,表示位置xi。
输出
输出仅一个整数,表示最大的最小距离值。
样例输入
复制样例数据
5 3
1 2 8 4 9
样例输出
3
提示
把牛放在1,4,8这样最小距离是3
2≤n≤105 , 0≤xi≤109, 2≤m≤n
之前做过一个题目与之类似:是跳石头这里链接
方法都一样我们每次枚举一个x判断它为 最小距离是否可行,如果可行我们保留到一个集合里,然后选出最大的可行值就是答案,不可行直接跳过,这种方法绝对可以筛选是没有问题的,答案也绝对是对的,但是复杂度太高 (稳TLE),所以还是二分,以后碰见最大最小值,最小最大值基本都是二分。
这里需要注意几个细节:
1.数据的范围:1e9出现警告 long long 安排上。
2.可行条件是,在这个距离下可以安放m头牛及包括m,但是第一头已经安排上了,所以条件为 tot>=2,tot为计数器。
然后代码附上:
#include <queue>
#include <cstdio>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <stack>
#include <algorithm>
#include <vector>
#define MIN(x,y) ((x)<(y)?(x) : (y))
#define MAX(x,y) ((x)>(y)?(x) : (y))
#define rl(a) scanf("%d",&a);
#include <sstream>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int mod=10007;
const int INF=1e9;
const int maxn=1e6+5;
ll a[maxn];
int n,m;
bool judge(int x)
{
ll now=a[1];
ll tot=1;
for(ll i=2;i<=n;i++)
{
if(a[i]-now>=x)
{
now=a[i];
tot++;
}
}
if(tot>=m) return true;//我们在判断时,已经假设第一头已经放了。
return false;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
sort(a+1,a+1+n);//不要忘记排序。
ll l=0,r=a[n]-a[1];
ll ans;
while(l<=r)
{
ll mid=(l+r)/2;
if(judge(mid)==true)
{
l=mid+1;
ans=mid;
}
else
r=mid-1;
}
printf("%lld\n",ans);
return 0;
}