二分木材长度,统计总共能切出的段数是否至少达到 k。
OJ: luogu
题目 ID: P2440
难度:普及-
标签:二分答案python
日期: 2026-06-18 20:11
题意
给出
思路
先看一个可以直接验证想法的朴素解:
在小数据上,我们可以把段长
cpp
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000 + 5;
int n;
long long k;
long long wood[MAXN];
bool check(long long len) {
long long cnt = 0;
for (int i = 1; i <= n; i++) {
cnt += wood[i] / len;
if (cnt >= k) return true;
}
return false;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> k;
long long mx = 0;
for (int i = 1; i <= n; i++) {
cin >> wood[i];
mx = max(mx, wood[i]);
}
long long ans = 0;
while (ans + 1 <= mx && check(ans + 1)) {
ans++;
}
cout << ans << '\n';
return 0;
}这个朴素解的问题在于,段长的范围最大可以到
- 固定一个段长
,怎么判断它能不能切出足够多的木段; - 如何更快地找到最大的可行
。
对固定的
因为段长越大,总段数越少,所以可行性具有单调性。 于是可以对段长二分,找到最大的可行值。
Python 知识
sum(log // length for log in logs)用整除计算每根原木能贡献的段数,再直接聚合。- 生成器不会创建“每根木头的段数”中间列表。
- 二分从
0开始,因此即使1cm也切不出,答案仍能自然落在0。 /home/rainboy/mycode/hugo-blog/content/program_language/python/generator_expression.md:一次性聚合使用生成器。/home/rainboy/mycode/hugo-blog/content/program_language/python/oj_input_output_cheatsheet.md:纯整数 token 的快速读取。
代码
python
import sys
data = list(map(int, sys.stdin.buffer.read().split()))
n, needed_pieces = data[:2]
logs = data[2:2 + n]
def enough(length):
return sum(log // length for log in logs) >= needed_pieces
left, right = 0, max(logs)
while left < right:
middle = (left + right + 1) // 2
if enough(middle):
left = middle
else:
right = middle - 1
print(left)复杂度
check(len) 需要扫描所有木头,复杂度是
所以总时间复杂度是
总结
这题是标准的“二分答案”。
关键在于把“能不能切出至少
一图流解析
这张图把本题的建模、关键转移、实现检查和训练方法压缩到一页,适合读完正文后复盘。
