[ABC174E] Logs 题解
思路
二分答案。
首先有两种特殊情况需要处理:
-
\(K = 0\):
我们无法执行切片操作,因此最短的 \(L\) 是当前最大的木棒长度。
-
\(K \geq \sum_{i=1}^{n}{A_i} - n\):
因为我们确实可以随意切下整个木棒。所以答案将是 \(\max(A)\)。
接下来考虑二分答案,令左右端点分别为 \(L\) 和 \(R\),中点为 \(mid = \lfloor\frac{L+R}{2}\rfloor\)。
对于每个木板 \(i\),计算它被切割多少次后长度会达到或超过 \(mid\)。如果总共切片操作的次数超过 \(K\),则必须缩小上限,即 \(R = mid-1\);否则必须增加下限,即 \(L=mid+1\)。
重复这个过程,直到 \(L=R\),此时最短的 \(L\) 是要求解的答案。
CODE
#include<bits/stdc++.h>
using namespace std;
int n,k;
long long a[200010];
bool poss(long long x){
long long cnt = 0;
for(int i = 1;i<=n;i++){
if(a[i]<=x)continue;//如果这根木材在>=x的情况下已经够砍了,那么就不需要再尝试
cnt += (a[i]+x-1)/x-1;//加上切几刀可以把长为a[i]的木头分成大小为x的小木棒
}
return cnt<=k;//是否符合操作数
}
int main(){
cin>>n>>k;
for(int i = 1;i<=n;i++){
cin>>a[i];
}
long long l = 0,r = 1000000000;//二分答案
while(r-l>=2){
int mid = (l+r)/2;
if(poss(mid))r = mid;//如果当前这个x可行,那么记录它
else l = mid;//否则将搜索右端点变小
}
if(poss(l+1))cout<<l+1<<endl;//注意小于等于的边界集与向上取整是一致的
else cout<<l<<endl;
return 0;
}

浙公网安备 33010602011771号