#5413. 二分答案笔记

二分答案笔记

二分答案笔记总结

一、什么是二分答案?

二分答案是一种基于二分查找思想的解题方法,用于求解满足特定条件的最优解(通常是最大值或最小值)。其核心思路是:通过对「可能的答案范围」进行二分,不断缩小范围,最终找到符合条件的最优解。

二分答案的关键前提:问题的解具有单调性。即:

  • 若某个值x满足条件,则所有小于x的值(或大于x的值)也满足(或不满足)条件。
  • 这种单调性保证了可以通过二分缩小范围。

二、二分答案的适用场景

当问题符合以下特征时,可考虑使用二分答案:

  1. 问题要求求解「最大的满足条件的值」或「最小的满足条件的值」;
  2. 答案的范围可以明确界定(有明确的上下边界);
  3. 对于某个候选值x,能快速判断其是否满足条件(即可以设计check函数)。

三、二分答案的基本步骤

  1. 确定答案范围:设定左边界l和右边界r(即可能的答案最小值和最大值);
  2. 设计check函数:判断候选值x是否满足问题的条件;
  3. 二分查找最优解
    • 计算中间值mid = (l + r) / 2
    • check(mid)判断mid是否满足条件;
    • 根据判断结果调整lr,缩小范围;
    • 重复上述过程,直到l > r,此时记录的最优解即为答案。

四、代码实例分析(木材切割问题)

以下代码解决的问题:
n棵树,高度分别为a[1]~a[n],现需要砍伐树木,使砍伐后所有木材的总长度至少为m。求最高的砍伐高度(即砍伐后每棵树的高度为x,高于x的部分被砍伐,求最大的x使得总砍伐量≥m)。

代码逐段解析

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,a[1000010];
  • 定义变量:n为树的数量,m为需要的木材总长度,a数组存储每棵树的高度。
bool check(int x){//判断砍伐高度为x的时候 是否满足条件 
    int sum=0;
    for(int i=1;i<=n;i++){
        if(a[i]>x)  sum+=a[i]-x;
    }
    return sum>=m;
}
  • check函数:核心是判断「砍伐高度为x时,总砍伐量是否≥m」。
    • 遍历每棵树,若树高a[i] > x,则砍伐部分为a[i]-x,累加总砍伐量sum
    • sum ≥ m,返回truex是可行的砍伐高度),否则返回false
signed main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    int l=1,r=1e9,ans;  // 步骤1:确定答案范围
    while(l<=r){        // 步骤3:二分查找
        int mid=(l+r)>>1;  // 等价于mid=(l+r)/2,避免溢出
        if(check(mid)){    // 若mid满足条件
            ans=mid;       // 记录当前mid为候选最优解
            l=mid+1;       // 尝试更大的x(因为要找最大可行值)
        }
        else{              // 若mid不满足条件
            r=mid-1;       // 只能尝试更小的x
        }
    }
    cout<<ans;
    return 0;
}
  • 主函数逻辑
    1. 输入数据:读入树的数量n、需要的木材m和每棵树的高度;
    2. 设定范围:l=1(最小可能高度),r=1e9(最大可能高度,可根据实际数据调整);
    3. 二分过程:
      • 计算中间值mid
      • check(mid)true:说明mid是可行的,但可能有更大的可行值,因此更新ans=mid,并将左边界右移(l=mid+1);
      • check(mid)false:说明mid不可行,需要更小的高度,因此将右边界左移(r=mid-1);
    4. 输出结果:循环结束后,ans即为最大的可行砍伐高度。

五、关键注意点

  1. 单调性分析:本例中,x越大,总砍伐量越少(单调性)。因此:

    • x可行(check(x)=true),则所有小于x的值也可行,但我们要找最大的x,因此需要尝试更大的范围;
    • x不可行(check(x)=false),则所有大于x的值更不可行,只能尝试更小的范围。
  2. 边界设置lr的初始值需覆盖所有可能的答案(如本例中树木高度不可能为负,故l=1r设为较大值)。

  3. check函数效率check函数的时间复杂度直接影响整体效率(本例中checkO(n),二分过程为O(log(max_a)),总复杂度为O(n log max_a),高效可行)。

六、总结

二分答案是解决「最优解问题」的高效方法,核心在于:

  • 识别问题的单调性;
  • 设计正确的check函数;
  • 合理设置边界并执行二分查找。

通过多练习类似「木材切割」「最小时间」「最大容量」等问题,可以快速掌握二分答案的应用。