二分小记

Posted zhuier-xquan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分小记相关的知识,希望对你有一定的参考价值。

二分的基本用途是在单调序列或单调函数中做查找操作。

二分,顾名思义,是不断将待求解区间平均分成两份,根据求解区间中点的情况来确定目标元素所在区间,这样就把解的范围缩小了一半。

二分算法的复杂度:O(二分次数*单次判定复杂度)

二分的写法:

整数域的二分:
int erfen(这里可以根据需要添加参数)
    int l=二分下界,r=二分上界,ans;
    while(l<=r)
        int mid=(l+r)>>1;
        if(check(mid)) ans=mid,l=mid+1;//这里求的是最小值最大问题
          else r=mid-1;
     
    return ans;


实数域的二分:
double erfen(这里可以根据需要添加参数)
    double l=二分下界,r=二分上界,ans;
    while(fabs(l-r)>dlt)
        double mid=(l+r)>>1;
        if(check(mid)) l=mid+1;
          else r=mid-1;
     
    return l;

二分常见的题型:

1.二分答案:最大值最小,最小值最大的问题:

我举个栗子:

数列分段Ⅱ

典型的二分问题,求最大值最小的问题;

首先确定二分上下界:上界显然不能超过数列中所有数的和,下界是这些数中最大的一个;

二分,套模板,因为是最大值最小的问题,所以不能套上面的二分模板,需要小改动一下,如果判断二分的答案可行,那么二分从l到mid-1;

其实感觉二分难在check函数上(至少我是这么觉得的qwq),因为题目要求是连续的才可以加和,所以我们从a[1]开始加,当某一个a[k]被加上以后超过二分值了,我们另计数器++,表示需要再分一组(小提示:计数器要从1开始记录而不是0),如果计数器<=要分的段数,表示这样分可行,否则不可行;

#include<bits/stdc++.h>

using namespace std;

int n,m,sum,mm;
int a[100010];

bool check(int z)
    int s=0,k=1;
    for(int i=1;i<=n;i++)
        if(s+a[i]>z)
            s=a[i];
            k++;
        
        else s+=a[i];
    
    if(k<=m) return 1;
    else return 0;


int erfen()
    int l=mm,r=sum,ans=0;
    while(l<=r)
        int mid=(l+r)>>1;
        if(check(mid)) ans=mid,r=mid-1;
          else l=mid+1;
    
    return ans;


int main()
    scanf("%d%d",&n,&m);
    
    for(int i=1;i<=n;i++)
      scanf("%d",&a[i]),sum+=a[i],mm=max(mm,a[i]);
    
    cout<<erfen()<<endl;

2.二分查找;

二分查找一般应用在有序的序列中。

这里不做过多解释qwq

 

以上是关于二分小记的主要内容,如果未能解决你的问题,请参考以下文章

20230413小记

KM算法学习小记:

带花树算法学习小记

SQLI-LABS 靶场通关小记(1~22)

SQLI-LABS 靶场通关小记(1~22)

五类常见算法小记 (递归与分治,动态规划,贪心,回溯,分支界限法)