首页 > 其他分享 >二分学习笔记

二分学习笔记

时间:2023-01-01 00:11:07浏览次数:53  
标签:二分 return int mid long 学习 算法 笔记

写在前面:本文中的“单调”不包括“单调不变”。(我不说你们应该也不会想到)

一、算法引入

如果我们要用一个数列(各个位置要有相应的数字形式的下标,且我们的这个下标可为小数)的某一个子序列来求一个值,那么当这个子序列的值是单调的,那么显然为了让我们整个过程的平均复杂度低一些,我们可以考虑使用这样或类似的算法:设\(l\),\(r\)分别代表现在搜索到的区间的左端点和右端点的位置,设一阈值\(x\),当位置\(x\)到区间[\(l\),\(x\)]包含我们要的答案时,l不变,r=x;否则r不变,l=x+y(y是一个非负数,具体的值自己定),r不变。(显然,阈值x取\(\lfloor\)(\(l\)+\(r\))/2\(\rfloor\)最好)

这样的算法大概就是二分算法了。

Tips:二分算法包括二分查找、二分答案、整体二分等算法。
这里我要先说一下,二分法刚学时你可能会感觉它很难,但只要你多模拟二分的过程,肯下功夫,你也会慢慢领悟到其中的奥妙了。(然后你也许就可以秒切各种二分可以做的很水的部分分,甚至直接用二分秒切很多题了(doge))

二、算法应用

2.1 二分查找

指在一个数列中用二分法来查找某个值。
例题一 Luogu P2249查找
\(Code\)&\(Explanation\)

#include<bits/stdc++.h>
using namespace std;
int a[1000005],m,q,n;
int find(int x){
    int l=1,r=n,mid;
    while(l<r){
        mid=l+r>>1;//下面五行为基本判断+端点修改
        if(a[mid]>=x){
        	r=mid;
        }
        else{
        	l=mid+1;
        }
    }
    if(a[r]==x){
    	return r;
    }
    else{
    	return -1;
    }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    for(int i=1;i<=m;i++){
        cin>>q;
        cout<<find(q)<<" ";
    }
    return 0;
}

2.2 二分答案

顾名思义,大概就是对某一个问题的答案进行二分,以求出一个最优解
例题一 Luogu P1873 EKO/砍树

\(Code\)&\(Explanation\)

//本题要我们求最大的一个可以得到至少M米木材的H
//我们可以发现,H值变大程中砍下木材的长度是单调不增的,那么我们就可以进行相关的二分答案了(以H为键值)
#include<bits/stdc++.h>
using namespace std;
long long a[2000000],m,n;
bool p(int h){
    long long ans=0;
    for(int i=1;i<=n;i++){
        if(a[i]>h){
            ans+=(a[i]-h);
        }
    }
    return ans>=m;
}
int main(){
    long long l=0,r=1e9,g,mid;
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
    }//下面的一段while循环为本题二分答案的主体部分
    while(l<=r){
        mid=l+(r-l)/2;
        if(p(mid)){//判断
        	g=mid;l=mid+1;//g是用来记录答案的
        }
        else{
        	r=mid-1;
        }
    }
    printf("%lld",g);
    return 0;
}

例题二 Luogu P1542 包裹快递
大体的算法与上一题的差不多,但要注意精度(lmid是用来防止死循环的)
\(Code\)&\(Explanation\)

//二分
//要用long double
#include<bits/stdc++.h>
#define F(i,j,k) for(int i=j;i<=k;++i)
#define ldb long double
using namespace std;
ldb l=0.0,r=10000000.0,ans=1.0*INT_MAX,ll=-1,rr=1;
int n;
struct node{
    int x,y,s;
}pos[200005];
int read(){
    int w=0;
    char c=getchar();
    while(c<'0'||c>'9')
        c=getchar();
    while(c>='0'&&c<='9'){
        w=(w<<3)+(w<<1)+c-'0';
        c=getchar();
    }
    return w;
}
ldb mmax(ldb aa,ldb bb){
    if(aa>=bb)
        return aa;
    return bb;
}
ldb mmin(ldb aa,ldb bb){
    if(aa<=bb)
        return aa;
    return bb;
}
int main(){
    n=read();
    F(i,1,n){
        pos[i].x=read();pos[i].y=read();pos[i].s=read();
    }ldb mid=l+r/2.00;
    while(l<=r){//ll=l,rr=r;
        bool ok=true;
        ldb mid=(l+r)/2.0;
        ldb tim=0.00;
        for(int i=1;i<=n;++i){
            ldb tt=1.00*pos[i].s/mid+1.00*tim;
            if(tt>1.00*pos[i].y){
                ok=false;
                break;
            }
            else{
                tim=mmax(tt,1.00*pos[i].x);
            }
        }
        if(ok&&mid<=lmid){
            r=1.0*mid-0.0001;
            ans=mmin(ans,mid);
        }
        else{
            l=1.0*mid+0.0001;
        }
    }
    printf("%.2Lf",ans);
    return 0;
}

2.3 整体二分

to be continued;

三、习题

3.1 Luogu P1102 A-B数对
to be continued;

本文如有什么大问题,请私信告知我或在本篇博客下评论告知我。

标签:二分,return,int,mid,long,学习,算法,笔记
From: https://www.cnblogs.com/4456q/p/17017637.html

相关文章

  • Day6:结束基础语法学习
    运算符补充部分+,-,*,/packageoperator;publicclassDemo01{publicstaticvoidmain(String[]args){//二元运算符//Ctrl+D复制当前......
  • DeepSTAPLE:UDA任务下学习多模态配准质量
    微信公众号:机器学习炼丹术笔记:陈亦新参考论文:DeepSTAPLE:Learningtopredictmultimodalregistrationqualityforunsuperviseddomainadaptation、参考code:​​multim......
  • riscv学习笔记
    Riscv是现在比较火的一套开源指令集(ISA),这就有很多搞头了,可定制化,不用收费,不像arm虽然很成熟,但是需要几百到几千万不等的授权费,对于小公司来说成本过于高昂。Sifive是Riscv......
  • .NET 云原生架构师训练营(基于 OP Storming 和 Actor 的大型分布式架构二)--学习笔记
    目录为什么我们用OrleansDaprVSOrleansActor模型Orleans的核心概念结合OPStorming的实践结合OPStorming的实践业务模型设计模型代码实现业务模型我们可以把关键......
  • 学习笔记282—SD与SEM有区别吗
    SD是标准偏差,反映的是样本变量值的离散程度。SEM是标准误差,反映的是样本均数之间的变异。SD为样本标准差,根据标准差SD能反映变量值的离散程度。正负值就是在计算好的SD上......
  • 修复U盘【笔记】
    修复U盘【笔记】​​前言​​​​参考​​​​修复U盘​​​​问题​​​​0.芯片精灵查看​​​​1.用APTool软件擦除量产信息​​​​2.用CBMTool量产U盘​​​​结果​​......
  • 在pycharm里debug以学习huggingface/transformers
    把https://github.com/huggingface/transformers整个zip下载下来把src/transformers文件夹复制出来,放pycharm里,成这样:根据https://github.com/huggingface/transform......
  • SAP MM 模块的入门者,想学习 ABAP 编程语言应该如何入手?
    本人自2007年计算机专业研究生毕业加入SAP成都研究院,在这之前也从未听说过ABAP这门编程语言,我算是ABAP零基础开始学习。根据我的过往经验,可以先简单了解一下ABAP......
  • 交流学习SAP ERP的各种问题和方法,如何快速入行?
    笔者从2007年大学计算机专业硕士毕业后加入SAP成都研究院从事SAP各种标准产品的设计和研发工作已经十五余年,期间也曾经在SAPERP上工作过一段时间,当然也包含SAP......
  • Stata学习笔记三
    usedentistsfdasavemydent,replace//replace选项如果新形成文件有同名存在直接覆盖保存为SASXPORT文件,扩展名为.xpttypemydent.xptlistduplicateslistrecom//有一......