【算法基础】二分

1. 整数二分模板


整数二分是求红色范围的右端点 或者 绿色范围的左端点

红色区间最右侧的那个点即是:序列中最后一个满足某条件(红色条件)的元素

绿色区间最左侧的那个点即是:序列中第一个不满足某条件(红色条件)的元素或是第一个满足某条件(绿色条件)的元素

定义check条件。如果判断mid < target, 那么找到的是小于target但是最接近target的数,就是小于target的最大数。如果判断mid >= target, 那么找到的是大于或者等于target的最接近target的数,就是target或者比target大的最小数。


cpp 复制代码
模板:

bool check(int x) {/* ... */} // 检查x是否满足某种性质

// 找右区间最左端点
// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;    // check()判断mid是否满足性质
        else l = mid + 1;
    }
    return l;
}

// 找左区间最右端点
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}
cpp 复制代码
#include <iostream>

using namespace std;

const int N = 1e5 + 10;
int arr[N];

int main()
{
    int n, q;
    scanf("%d%d", &n, &q);
    for (int i = 0; i < n; i++) scanf("%d", &arr[i]);

    while (q--)
    {
        int l = 0, r = n - 1, x, mid;
        scanf("%d", &x);
        // 1 2 2 3 3 4 找第一个3即右区间最左端点
        while (l < r)
        {
            mid = l + r >> 1;
            if (arr[mid] >= x) r = mid;
            else l = mid + 1;
        }
        if (arr[l] != x) // 若找不到
            cout << "-1 -1" << endl;
        else // 找左区间的最右端点
        {
            cout << l << " " ;
            l = 0, r = n - 1;
            while (l < r)
            {
                int mid = l + r + 1 >> 1;
                if (arr[mid] <= x) l = mid;
                else r = mid - 1;
            }
            cout << r << endl;
        }
        
    }
    return 0;
}

2. 浮点数二分模板

cpp 复制代码
bool check(double x) {/* ... */} // 检查x是否满足某种性质

double bsearch_3(double l, double r)
{
    const double eps = 1e-6;   // eps 表示精度,取决于题目对精度的要求
    while (r - l > eps)
    {
        double mid = (l + r) / 2;
        if (check(mid)) r = mid;
        else l = mid;
    }
    return l;
}

A. 方程求根类(最直观)

题 1:求解方程根(单调)

给定实数 a,ba,ba,b(保证存在唯一解),求方程x3+x=ax^3 + x = ax3+x=a的解,输出保留 6 位小数。
check 设计x^3 + x >= a(左边随 x 严格递增,单调)。

题 2:对数/指数方程

给定 a>0a>0a>0,求满足
ln⁡(1+x)=a \ln(1+x)=a ln(1+x)=a

的 xxx(唯一解),保留 6 位小数。
checklog(1+x) >= a(单调递增)。
区间l=0, r=...(可取大一点,例如 r=1e6)


B. "最小值/最大值 + 可行性"类(最常见的二分答案)

题 3:最小时间完成任务(机器生产)

有 nnn 台机器,第 iii 台每生产 1 件需要 tit_iti 秒。问最少多少秒能生产至少 MMM 件?输出保留 6 位小数(允许机器连续生产,时间是实数)。
check(T) :计算 ∑⌊T/ti⌋≥M\sum \lfloor T/t_i \rfloor \ge M∑⌊T/ti⌋≥M 是否成立。

  • 单调性:T 越大能生产越多,更容易满足(false→true)。

这是经典"最小时间"模型,整数/浮点都能做,若题目允许连续或要求小数,就用浮点二分。

题 4:最小加油速度(到达不晚)

你要在 DDD 公里内赶到,最晚时间 TTT 小时。车速 vvv 可取实数,问最小 vvv 使得 D/v≤TD/v \le TD/v≤T。
check(v)D / v <= T(v 越大越容易满足)。


C. 几何覆盖/距离类(半径、距离、阈值)

题 5:最小半径覆盖所有点(圆覆盖)

给定平面上 nnn 个点,和一个固定圆心 CCC。求最小半径 RRR,使得圆心为 CCC 的圆覆盖所有点。
check® :判断所有点到 CCC 的距离是否都 ≤R\le R≤R。

  • 单调性:R 越大越容易覆盖。

(这题其实能直接算最大距离,但它是让你练"浮点二分 + 单调覆盖"的直觉。)

题 6:一维点用 k 个区间覆盖(最小区间长度)

给定数轴上 nnn 个点,允许用 kkk 个长度为 LLL 的闭区间覆盖所有点。求最小 LLL。
check(L) :贪心从左到右放区间,看能否用 ≤k\le k≤k 个覆盖完。

  • 单调性:L 越大越容易覆盖。

D. 最大化某个"比值/平均值"的经典套路

题 7:最大平均值子段(或选 k 个物品的最大平均)

给定数组 a1..ana_1..a_na1..an,求长度至少为 mmm 的连续子段最大平均值,输出 6 位小数。
二分答案 avg

把每个数变成 bi=ai−avgb_i = a_i - avgbi=ai−avg,问是否存在长度 ≥ m 的子段使得 ∑bi≥0\sum b_i \ge 0∑bi≥0。
check(avg):用前缀和 + 最小前缀判定是否存在这样的子段。

  • 单调性:avg 越大越难达到(true→false 或反过来,取决于你写的 check)。

这是"二分答案 + 判定"的代表题型之一,含金量很高。

题 8:最大化单位成本收益(分数规划)

有 n 个项目,第 i 个项目收益 pip_ipi、成本 cic_ici,你必须选恰好 k 个项目,最大化 ∑p∑c\frac{\sum p}{\sum c}∑c∑p。
二分 ratio

令 bi=pi−ratio⋅cib_i = p_i - ratio \cdot c_ibi=pi−ratio⋅ci,问是否能选 k 个使得 ∑bi≥0\sum b_i \ge 0∑bi≥0。
check(ratio) :把所有 bib_ibi 排序取最大的 k 个看和是否 ≥ 0。

  • 单调性:ratio 越大越难满足。

E. 物理/概率/连续过程类

题 9:混合浓度(最小倒入量达到目标浓度)

有两种溶液浓度 c1,c2c_1,c_2c1,c2,你要混合成浓度至少为 CCC,其中第一种倒入量为 xxx(实数),总量固定为 VVV。求最小 xxx。
check(x):混合浓度是否 ≥ C(关于 x 线性单调)。


你做题时的"识别口诀"

看到这些特征就该想到浮点二分:

  1. 答案是实数(要保留若干位小数 / 允许误差)
  2. 能写 check(x):给定 x 判断"可不可以/行不行/是否满足不等式"
  3. check 随 x 单调(只翻一次)
相关推荐
ffqws_1 分钟前
进阶搜索:迭代加深搜索(IDS)埃及分数题解
算法·迭代加深
格林威1 分钟前
相机的“对焦”和“变焦”,这二者有什么区别?
开发语言·人工智能·数码相机·opencv·算法·计算机视觉·视觉检测
LXS_3572 分钟前
常用算法(下)---拷贝、替换、算术生成、集合算法
开发语言·c++·算法·学习方法
历程里程碑2 分钟前
Linux19 实现shell基本功能
linux·运维·服务器·算法·elasticsearch·搜索引擎·哈希算法
鲨辣椒100864 分钟前
算法也能降低时间复杂度???—————算法延伸
数据结构·算法·排序算法
你怎么知道我是队长6 分钟前
C语言---排序算法5---迭代归并排序法
c语言·算法·排序算法
拼好饭和她皆失9 分钟前
数学知识:质数相关讲解——质数判定,分解质因数及筛质数
算法·质数·数学知识
想进个大厂11 分钟前
代码随想录day35 36
算法·leetcode·职场和发展
xqqxqxxq12 分钟前
洛谷算法1-2 排序(NOIP经典真题解析)java(持续更新)
java·开发语言·算法
嵌入小生00713 分钟前
数据结构 | 常用排序算法大全及二分查找
linux·数据结构·算法·vim·排序算法·嵌入式