返回顶部

二分答案与二分查找

二分答案与二分查找

一. 适用范围

​ 如果序列是有序的,就可以通过二分查找快速定位所需要的数据。除此之外,二分思想还能求出可行解的最值问题,如最小的最大值,最大的最小值等等

二.使用方式

​ 二分时首先要确定上下界 \(leftbound\) 以及 \(rightbound\) ,然后取其中间值 \(middle\) , 通过 \(check\)

函数来用 \(middle\) 更新上界或下界

两种不同的代码构造

void erfen()
{
    int l=0,r=1e10;
    while(l <= r)
    {
        int mid = (l + r) / 2;
        if(check(mid)) ans = mid , l = mid + 1;
        else r = mid - 1;
    }
    printf("%d",ans);
}

void erfen()
{
    int l=0,r=1e10;
    while(l + 1 < r)
    {
        int mid = (l + r) / 2;
        if(check(mid)) l = mid;
        eles r = mid;
    }
    printf("%d",l);
}

第一种方式:不使用上下界作为答案,而是在每一次 \(mid\) 成立时刷新答案 \(ans\) ,将 \(mid\) 抛出 \(l\)\(r\) 范围,\([l,r]\) 区间内的每个点都有成为答案的可能,所以只有在区间为空时跳出循环,即循环条件是 \(l<=r\)

第二种方式:使用上下界作为答案,此时可以发现,\(mid\) 成立时刷新的是 \(leftbound\) ,而不成立时刷新 \(rightbound\)\(l\) 在答案内,\(r\) 在答案外。所以答案区间是 \([leftbound,rightbound)\) 左闭右开区间。所以 \(l<r\) 恒成立,当 \(l+1==r\) 时,二分结果已经出现,此时跳出循环,输出 \(l\) 作为答案。故循环条件是 \(l+1<r\)

三.注意事项

​ 二分题目有时会精确到小数,此时最好使用第二种二分方式,为确保精度,设 \(eps=10^{-8}\) , 以 \(r-l>eps\) 作为边界条件。此时要注意,\(eps\) 精度不能过大,否则复杂度过高会TLE,一般选择 \(10^{-6}\) 就可以了。

​ 切勿忘记开 long long , 任何题都一样

小数精度模板:

#define eps 1e-8
void erfen()
{
    double l=0,r=1e10;
    while(r-l > eps)
    {
        double mid = (l+r)/2.0; //除法要带小数点保精度
        if(check(mid)) l = mid;
        else r = mid;
    }
    printf("%.10lf",l);
}
posted @ 2022-06-29 21:07  魔幻世界魔幻人生  阅读(64)  评论(2)    收藏  举报