当前位置: 首页 > news >正文

整数二分·二分的思想与模板·经典二分题:数的范围


单值查找,更适用于有单调性的区间,没单调性的区间,也有可能能用

二分的思想

一.确定一个区间,使得目标一定在区间中(目标一定是单值)

二.找一个性质,满足两点

1.性质具有二段性 区间上每个数都可以判断是否满足这个性质,满足下列条件

2.答案,是二段性的分届点(百分之95满足这个条件)

整数二分

求第一段最后一个结果,用l=mid,r=mid-1;

求第二段第一个结果,用r=mid,l=mid+1;

活动 - AcWing

整数二分理论性质

20230210_151052.mp4

定义判断条件时注意,判断条件为真时,答案一定在该区间内,或者说,区间内一定要包含答案

模版1

	while(l<r){
            int mid=(l+r)>>1;
            if(判断条件)r=mid;//要求,判断条件为真时,答案一定在该区间内,区间内一定要包含此答案
            else l=mid+1;
        }
// 我们最终要找的边界是一个性质在右半区符合,在左半区不符合的性质。
//我们要找符合的右半区的左边界点。管中窥豹的判断check(mid)
//如果mid符合条件Mid是在右半区符合性质的半区中。要找左边界点的范围则更新为r = mid(包含Mid)。
//如果mid不符合条件,我们要找符合性质的左端点则l = mid + 1(已经确定mid是不符合的就从mid+1开始算)

模版2

判断条件为l=mid时,l+r+1

 while(l<r){
                int mid=(l+r)+1>>1;
                if(判断条件)l=mid;
                else r=mid-1;
        }
//+1是因为,如果l=r-1的时候,不加1会导致重复死循环
//例如下面,假如l=1,r=2,判断条件成立,会发生什么
				int mid=(l+r)>>1;//1+2除以2等于1.5,int类型向下取整,mid等于1
                if(判断条件)l=mid;//判断条件成立,l=mid,则l=1,初始状态l也=1,陷入无限循环
                else r=mid-1;

数的范围,这题不错,用到两个模板,下面是解答代码,题目acwing,洛谷都有。

#include<iostream>
#include<cstdio>
using namespace std;
int arr[100010];
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=0;i<n;i++)cin>>arr[i];
    for(int i=0;i<m;i++)
    {
        int o;
        cin>>o;
        int l=0,r=n-1;
        while(l<r)
        {
            int mid=(r+l)/2;
            //把这个数组划分成了两段性质,一段小于o,一段大于等于o
            //我们要求的是第二段第一个
            //>=o,mid符合条件,可能是第二段第一个,也可能不是
            //因为o现在可能是mid本身或者mid左边的数,所以只需要移动r,r=mid
            if(arr[mid]>=o)r=mid;//判断条件,为真时,一定要包含答案
            else l=mid+1;
            //这里是表示mid<o,则答案一定在mid右侧,且一定不是mid本身,因为区间1里没有o
            //在mid右侧,把l移过来,因为答案不在原来的l到mid的区间,所以再右移1
            //变成区间mid+1到r,答案在这个区间内
        }
        
        if(arr[r]==o)
        {
            cout<<r<<' '; 
            l=r;//在这个区间内是有单调性的
            r=n-1;
            while(l<r) 
            {
               int mid=(r+l)+1>>1;
                //因为写的是l=mid,所以r+l+1
               if(arr[mid]<=o)//这里把等于永远写在第一个判断里,才能符合更新理论性质,不用加减
                l=mid;//这里是l,所以(r+L)+1再除以2
               else r=mid-1;
            //因为等于情况在上面,下面判断条件r或者l本身肯定不等于所找点,r向左移,l向右移
            }
            cout<<r<<endl;
        }
        else
        cout<<"-1 -1"<<endl;
    }
    return 0;
}

整数二分一直找到中间唯一一个数,而实数二分不同

实数二分

实数二分是一直找到足够小的某个数

例如

while(l<r)//这是整数二分判断条件,其实也可以看成
while(l!=r)//当l=r时候,就只剩下一个整数,结果就是ans(答案)
//但如果是实数二分,这里我们这么写
while(r-l>1e-6)

注意,题目主有要求取到第几位小数,我们要多取至少两位,保证精度

例如

题目要求取小数点后6位,我们的循环写成

while(r-l>1e-8)

while(r-l>1e-8)

很重要!!

二分适合求最大最小

经典题目

AcWing - 算法基础课

#include<iostream>
#include<cstdio>
using namespace std;
double l,n,r;
int main(){
    cin>>n;
    l=-10000,r=10000;
    while(r-l>1e-8){
        double mid=(r+l)/2;
        if(mid*mid*mid>=n)r=mid;
        else l=mid;
    }
    printf("%.6lf",r);
    return 0;
}

相关文章:

  • 面基:雪花算法Snowflake时钟回拨问题解决方案
  • Redis 服务端主动回收配置
  • 项目实战 - 用户列表
  • AIP-203 域行为文档
  • MyBatis执行批量插入sqlserver报错:不允许从数据类型 varbinary 到 datetime2 的隐式转换
  • PowerBi 桑基图(SanKey)显示多节点的解决方法
  • 数据结构与算法基本概念
  • 使用大语言模型进行Python图表可视化
  • 【质量管理】质量的系统是预防,那以预防为主的质量管理系统包括什么?
  • 【QT】练习1
  • 里昂惕夫矩阵:投入产出分析
  • element-plus走马灯(el-carousel)不显示问题
  • 【数论3】裴属定理与扩展欧几里得算法
  • naive_admin项目实战03 基于Go语言的后端
  • LearnOpenGL小练习(QOpenGLWidget版本)
  • 【杂谈】-大型语言模型对具身人工智能发展的推动与挑战
  • Apache Hive和Snowflake的`CREATE VIEW`语法和功能特性整理的对比表
  • 移动端六大语言速记:第5部分 - 面向对象编程(OOP)
  • 翻译: 人工智能如何让世界变得更美好三
  • 深入解析HTTP请求方法:Spring Boot实战与最佳实践
  • 乔智云智能建站/今日新闻摘抄10条简短
  • 乐站_网站建设_自助建站/南宁seo服务优化
  • 最新wordpress 优化版/福州短视频seo服务
  • 青岛市城乡建设委员会官网网站/seo查询平台
  • 网站开发php工程师/泰州网站整站优化
  • 男科医院网站建设策略/关键词优化资讯