[ABC174E] Logs 题解

思路

二分答案。

首先有两种特殊情况需要处理:

  1. \(K = 0\)

    我们无法执行切片操作,因此最短的 \(L\) 是当前最大的木棒长度。

  2. \(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;
}
posted @ 2023-08-13 10:46  _Unnamed  阅读(19)  评论(0)    收藏  举报