前言
二分答案是算法竞赛与笔试中极具技巧性的高分解法,核心思路是将复杂求解转化为简洁的二分 + 判定,专门解决「最大值最小」「最小值最大」等经典问题。本文从原理到实战,结合两道高频例题,带你从零掌握二分答案的核心逻辑与代码模板。
一、二分答案
严格来说,二分答案应该叫做「二分答案 + 判断」。它主要处理大部分「最大值最小」以及「最小值最大」的问题。如果解空间在从小到大的变化过程中,判断答案的结果出现二段性(即满足条件的部分和不满条件的部分各占一段),此时我们就可以对解空间进行二分,通过判断函数找出最优解。
二、二分答案经典算题
2.1 木材加工
题目
给定 N 根原木,长度分别为 a[1]...a[N]。现在需要切出 K 段长度相等的木条,问每段木条的最大长度是多少?
算法原理
这道题是典型的「最大化最小值」问题。假设我们切出的长度为 x,那么对于每一根原木 a[i],可以切出 a[i]/x 段。总段数 sum(a[i]/x) 必须大于等于 K。
随着 x 的增大,能切出的段数会单调递减;随着 x 的减小,能切出的段数会单调递增。这种单调性使得我们可以使用二分查找来确定最大的 x。
代码
#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 ((mid) >= k) l = mid;
r = mid - ;
}
cout << l << endl;
;
}


