传送门:SP297
这道题本质就是查找在牛尽可能接近的情况下,找到牛之间距离的最大值
也就是说牛之间的答案距离越小,牛棚能放的牛就越多。
假设把牛棚之间的距离看成一条线段,我们可以肯定第一个牛放在线段原点的位置。
然后我们设置一个牛与牛之间的间隔距离tmp=0和当前已经在牛棚的牛数cnt=1(第一头牛肯定在线段原点)。
由于牛棚的距离是固定的,所以我们需要枚举牛棚a[i]-a[i-1]之间的距离,累加到tmp上,用以表示两头牛身处牛棚时,它们之间实际上的间隔距离。
我们当前二分的最近两头牛之间距离的最大值为mid
当tmp>=mid时,就说明当前满足了最近两头牛之间距离的最大值,说明我们在第i个牛棚可以放下一头牛。
于是当前牛的数量cnt++
最后如果给定要放入的牛数c>cnt,这就说明我们放的牛太少了,因为我们假设的两头牛之间的距离mid太大了
因此c>cnt为true时=> hi=mid,我们就把二分的上界减少。
反之同理。
(我的二分是左闭右开区间**[lo,hi)**,因此写法会略有不同,但易于证明是正确的,而根据这种写法,最终当lo==hi时会变成(lo,hi),因此需要lo-1才可以输出正解) qwq
完结撒花,谢谢各位~
#include<bits/stdc++.h>
#define For(i,m,n) for(int i=m;i<n;i++)
#define reset(a) memset(a,0,sizeof(a))
using namespace std;
template <class T>
inline void read(T &x)
{
x=0;T f=1;
char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
x=x*f;
}
const int MAX=1e6;
int T,n,c;
int a[MAX];
bool check(int mid)
{
int cnt=1;
int tmpSum=0;
For(i,2,n+1){
tmpSum+=a[i]-a[i-1];
if(tmpSum>=mid){
cnt++;
tmpSum=0;
}
}
if(c>cnt) return true;
else return false;
}
int main()
{
read(T);
For(i,0,T){
read(n);read(c);
reset(a);
For(j,1,n+1) read(a[j]);
sort(a+1,a+n+1);
int lo=0,hi=1e8;
while(hi!=lo){
int mid=(lo+hi)/2;
if(check(mid)) hi=mid;
else lo=mid+1;
}
cout<<lo-1<<'\n';
}
return 0;
}