二分边界小总结

二分主要应用于最小化最大值和最大化最小值;

边界:
我的习惯是半闭半开的写法;
即答案在[ l , r )的范围中或答案在( l , r ]的范围中;

注意是答案在[ l , r )中;
所以 l 并不一定永远等于0或1,它是答案的左边界,而r是答案的右边界+1;
另一种情况同理;

所以说,有时候你写的二分是错误的…..只是没有坑爹的数据卡你……

最小化最大值

答案范围 : ( l , r];

例题:https://www.luogu.org/problemnew/show/1182

这道题的左边界是区间的最大值,而不是 1或 0;
如 : 5 5 1 2 3 7897979 4
输出:7897979;
所以l一定要设为最大值-1;

    l--;
    while(r - l >1)
    {
        int mid=(l+r) >> 1;
        if(check(mid)) r=mid;//如果可行,看是否可以继续缩小最大值
        else l=mid;
    }

退出条件是 l + 1 == r
答案是 r ;

最大化最小值

答案范围 : [ l , r );

例题:NOIP2012 跳石头

这道题有个数据是:
65343245 0 0 (没有石头=_=,好坑啊);
输出 :65343245

r一定要设为总距离+1,因为r并不是你的答案右边界,而是答案右边界+1;

   r++;
   while(r - l > 1)
    {
        int mid=l+r >>1;
        if(check(mid)) l=mid;//如果可行,看是否可以增加最小值;
        else r=mid;
    }

退出条件 : l + 1 == r
答案是 l

总结

1、对于半闭半开的写法,总是有一方的初始值为答案边界+1或-1;
2、注意以上两种写法是不同的

小技巧?

如果不知道答案边界或者不知道输出l还是r怎么办?(好像并不存在<-_<-);

1、可以对r设一个极大值;
2、输出答案是将边界check一下,输出返回true的那个,
例如 : 跳石头;
如果边界设为l=0,r=sum;
加上这句话,那个坑爹的点也能过;

if(check(r)) l=r;//检查二分的上界是否满足;
    cout<<l;

3、二分时保存一下答案,仅限于左闭右闭的写法;

希望大家有所收获~ ~ ~ ~ ~ ~ ~ ~

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值