二分小记
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
以上是关于二分小记的主要内容,如果未能解决你的问题,请参考以下文章