整数二分详解及例题

整数二分的目的:
查找
整数二分的思想:
每次留下一半,保证答案在这一半里
整数二分实现的具体步骤:
(1)根据问题分析,确定是左区间还是右区间,mid在哪个区间
(2)根据区间,判断l与r的取值,再根据l与r的取值,确定mid是否有+1
(3)二分的while循环的终止条件是l==r,即为答案。

bool check(int mid)
{

}
//两个整数二分模板,用哪个具体问题具体分析
//[l,mid]用来找l,求左边界,左区间
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 1;
}
//[mid,r]用来找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 1;
}

写一个check函数,根据check判断如何更新l或r,两种模板的区别在于是否有+1
1.对于r = mid的情况,避免区间不变,中间值需使用(l + r) >> 1,另一个分支一定是l = mid + 1。
2.对于l = mid的情况,避免区间不变,中间值需使用(l + r + 1) >> 1,另一个分支一定是r = mid - 1。
上面两种情况mid的取值实际一个是下取整,另一个是上取整,原因是为了避免区间不变,导致死循环。解释如下:
请添加图片描述
在这里插入图片描述
例题:Acwing 789. 数的范围
解答:

/*
  有单调性必定可以二分,可以二分的不一定有单调性
  测试用例
6 3

1 2 2 3 3 4

3

4

5
*/
#include<iostream>
#include<algorithm>
using namespace std;
const int N=10010;
int t[N];
int main()
{
    int n,q;
    cin>>n>>q;
    for(int i=0;i<n;i++)
    {
        cin>>t[i];
    }
    for(int i=0;i<q;i++)
    {
        int k;
        cin>>k;
        int l=0,r=n-1;
        while(l<r)//找起始位置,在左区间
        {
            int mid= l+r>>1;
            //应该更新成[l,mid]
            if(k<=t[mid])r=mid;
            else l=mid+1;
        }
        if(t[l]!=k) cout<<"-1 -1"<<endl;
        else
        {
            cout<<l<<' ';
            while(l<r)//找终点,在右区间
            {
                int mid=l+r+1 >>1;
                if(k>=t[mid])l=mid;
                else r=mid-1;
            }
            cout<<r<<endl;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值