前言
二分答案是算法竞赛中极具技巧性的解法,核心在于将复杂求解转化为'二分 + 判定'。它专门解决「最大值最小」或「最小值最大」类问题。只要解空间具有单调性(二段性),就能通过二分快速锁定最优解。
一、二分答案原理
准确来说,这属于「二分答案 + 判断」。当解空间从小到大变化时,如果判定结果呈现「满足」到「不满足」的跳变,即可二分。我们不需要直接求出答案,而是验证某个猜测值是否可行。
二、经典例题实战
1. 木材加工
题目描述 给定 N 根原木,长度分别为 $a_1, a_2, …, a_N$。需要切成至少 K 段等长的木料,求每段的最大长度。
思路分析 假设切出的长度为 $x$,那么第 $i$ 根木头能切出 $⌊ a_i / x ⌋$ 段。总段数 $∑ ⌊ a_i / x ⌋$ 随 $x$ 增大而减小。这是一个典型的单调性问题。我们要找最大的 $x$,使得总段数 $≥ K$。
代码实现
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
typedef long long LL;
LL a[N], n, k;
// 计算在切割长度为 x 的情况下能切几段
LL calc(LL x) {
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];
// 二分范围:左边界 0,右边界最大可能长度 1e8
int l = 0, r = 1e8;
while (l < r) {
// 向上取整,避免死循环
LL mid = (l + r + 1) / 2;
if (calc(mid) >= k) {
l = mid;
} {
r = mid - ;
}
}
cout << l << endl;
;
}


