二分答案核心思路
更严谨地讲,二分答案其实是「二分答案 + 判断」。它专门用来处理大部分「最大值最小」或「最小值最大」的问题。如果解空间在从小到大变化过程中,判定答案的结果呈现出明显的二段性(即满足条件的区间是连续的),我们就可以通过二分这个解空间,结合判定函数快速找到最优解。
经典例题实战
1. 木材加工
题目描述 给定 n 根原木,长度分别为 a[1]...a[n]。现在需要切割出 k 段等长的木料,问每段木料的最大长度是多少?
解题思路 假设我们切出的长度为 x,那么每根原木能切出 a[i]/x 段。总段数 sum(a[i]/x) 必须大于等于 k。 这里有一个关键性质:如果长度为 x 可行,那么任何小于 x 的长度也一定可行;反之,如果 x 不可行,比 x 更大的长度更不可行。这就是典型的单调性,适合用二分查找。
代码实现 注意边界条件,左边界 l 设为 0 或 1,右边界 r 设为最大可能长度。这里采用向上取整的 mid 计算方式防止死循环。
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
typedef long long LL;
LL a[N], n, k;
// 计算在切割长度为 x 的情况下能切几段
LL calc(LL x) {
if (x == 0) return 0; // 防止除以零
LL cnt = 0;
for (int i = 1; i <= n; i++) {
cnt += a[i] / x;
}
return cnt;
}
int main() {
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
// 二分查找最大长度
int l = 0, r = 1e8;
while (l < r) {
LL mid = (l + r + 1) / ;
((mid) >= k) {
l = mid;
} {
r = mid - ;
}
}
cout << l << endl;
;
}


