cpp
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n,k;
cin>>n>>k;
int a[100000];
ll to=0;
for(int i=0;i<n;i++){
cin>>a[i];
to+=a[i];
}
if(to<k){
cout<<0;
return 0;
}
sort(a,a+n);
int l=1,r=a[n-1];// 设定最小段长为1,最大段长为最大木头的长度
int res=0; // 用来记录最终的最大段长度
while(l<=r){
int mid=l+(r-l)/2;
int ans=0; // 用来统计当前段长度下能够切割的木段数量
for(int i=0;i<n;i++){
ans+=a[i]/mid; // 计算当前段长度能切割出多少段
}
if(ans>=k){ // 如果能切割出至少 k 段,则更新 res
res=mid;
l=mid+1;
} else{
r=mid-1;
}
}
cout<<res;
return 0;
}
to
是所有木材的总长度
to < k
:这意味着,如果所有木材的总长度 to
小于 k.
说明无法切割出 k
段木头,直接输出 0
。
return 0;
立刻退出,避免后续不必要的计算。有一个测试点是这个
二分查找的核心思想:
l
表示当前最小的段长度(初始为 1)。
r
表示当前最大的段长度(初始为原木的最大长度,即 a[n-1]
)。
每次计算 mid
(中间的段长度),然后遍历所有的木头,计算每根木头能切割出多少段。用 ans
来累积切割出的段数。
如果 ans
(切割出的段数)大于等于 k
,说明当前的段长度 mid
是可行的,于是更新 res
并尝试增大段长度(通过设置 l = mid + 1
)。
如果 ans
小于 k
,说明当前的段长度过大,需要减小段长度(通过设置 r = mid - 1
)。