二分模版

本文详细探讨了二分查找的整数域和实数域应用,包括两种不同的二分模板,强调了处理mid位置的正确方式以及无解情况的处理策略。特别指出在整数域中,二分过程中应使用右移运算来确保正确性。

之前二分一直用lower_bound,遇到麻烦的题不方便。仔细研究二分真的有很多细节的点。

  • 二分模板一共有两个,主要看mid在期望答案的右边还是左边
  • 二分过程全部使用右移运算>>1而不是/2。因为右移运算是向下取整,而整数除法是向零取整,在二分值域包含负数时后者不能正常工作

整数域上二分
1. mid在期望答案的右边(mid大)
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = (l + r) >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    return l;
}
2. mid在期望答案的左边(mid小)
  • 缩小范围时,l=midr=mid-1,中间值mid=(l+r+1)>>1,如果中间值取mid=(l+r)>>1,则当r-l=1时,有mid=(l+r)>>1=l,接下来若进入l=mid分支死循环;若进入r=mid-1分支,造成l>r,循环不能以l=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;
}
3. 处理无解情况:

因为mid = (l+r)>>1不会取到r这个值,mid = (l+r+1)>>1不会取到l这个值
把[1,n]扩大为[1,n+1]和[0.n],把a数组的一个越界下标包含进来,如果最后二分终止于扩大后的这个越界下标上,则a中不存在所求的数。


实数域上二分

一般保留k位小数时,取eps=10−(k+2)eps=10^{-(k+2)}eps=10(k+2)

while (l+1e-5 < r)
{
	double mid = (l + r) / 2;
	if (calc(mid)) r = mid;
	else l = mid;
}

或者直接使用固定次数的二分,精度会更高,但容易超时

for (int i = 0; i < 100; i ++)
{
	double mid = (l + r) / 2;
	if (calc(mid)) r = mid;
	else l = mid;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值