二分顾名思义
其实就不断的把东西分为两半
二分自古就有html
二分在数学中,也有应用,例如零点存在性定理ios
\(设y=f(x) 若是f(x)在 [a,b]上连续 且 f(a)*f(b)<0 则[a,b]之间存在零点\)学习
只须要经过不断的二分就能够找到零点ui
今天主要介绍两种二分的应用
spa
二分查找:是经过二分的方法来查找code
codehtm
int l=1,r=7,mid; int s[9]={0,1,5,8,9,11,20,33}; int k=1//咱们要查找的数 while(l<=r){ mid=(l+r)>>1;//等价于(l+r)>>1 if(k<=s[mid]) r=mid-1; else l=mid+1; } if(s[l]==k) printf("存在"); else printf("不存在");
二分答案,二分的对象是答案,但二分的对象有具备单调性对象
因此只有当答案具备单调性的时候能够进行二分blog
并且须要能找出答案的范围排序
最后就是check(答案),判断最终答案在左区间仍是右区间最终获得答案
例题选讲
通常看见这种最大值的最小值也有可能用二分答案
首先咱们须要肯定具备单调性
求得相邻两头牛最近距离得最大值,由于距离嘛,要么长要么短,短的变到长,具备单调性实锤
那范围了?
最小值:能够为两个隔间的最小距离
最大值:两个相距最远得隔间得差
很容易看出来
(稍微讲下缘由,懂得同窗就日后看把
借用刚刚的例子最大值为8
答案还能取9吗?显然不能,因你取9的话,此时也不存在两个隔间相距离为9
check环节
举栗
1,2,4,8,9
最小值:1
最大值:8
即\(ans∈[1,8]\)
取中间值 4
从第1个隔间开始放1头牛,找到
下1个隔间>=4四的隔间放第2头牛,即在第4个隔间放
结果你会发现下1头牛,没有位置可放了,这说明什么?
这说明最近距离太大了,并不满题意(好好理解一下
则答案必定在[1,3]之间(由于若是距离>=4,是否是能放的牛可能更少
取中间值 2
从第1个隔间开始放第1头🐂
那么第2头🐂则会放在第3个隔间
第3头🐂会放在第5个隔间
放完了全部🐂,也知足题意
那么这个是否是最终答案了?
(还有待观察
好既然最近距离为2时必定知足其条件,那么距离比2小的也一样知足(这里须要思考一下,其实也挺简单~
那比2大的距离可不可能知足条件?
(**有可能**,此时距离2知足题意只能说明距离2确实是一种答案,但注意此时[2,4]之间也可能存在答案,也许多放一格距离也可能知足题意)
此时取[2,3]中间值3
从第1个隔间开始放第1头🐂
那么第2头🐂则会放在第3个隔间
第3头🐂会放在第5个隔间
放完了全部🐂,也知足题意
此时区间为[3]
此时就找到最近距离的最大值
回放一遍咱们模拟过程
判断其答案是否知足题意,排除不知足的区间,留下知足的区间,最终找到最终答案
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; int n,c;const int maxn=1e5+10; int m[maxn]; int st[maxn],top=1; long long l=1e9,r; bool check(long long mid){ int tot=1;st[top]=m[1];top=1; for(int i=2;i<=n;++i) if(m[i]-st[top]>=mid) ++tot,st[++top]=m[i]; return tot>=c; } int main(){ cin>>n>>c; for(int i=1;i<=n;++i){ cin>>m[i]; if(i>=2) l=min((long long)m[i]-m[i-1],l); } sort(m+1,m+1+n);r=m[n]-m[1]; long long mid; while(l<=r){ mid=(l+r)>>1; if(check(mid)) l=mid+1; else r=mid-1; }cout<<r<<endl;return 0; }
二分查找
查找的关键字必定具备单调性
(若是二分对象无序,那么须要排序,排序的学习笔记
二分答案
其实二分本质也是枚举,在一种特殊具备单调性序列或其余具备单调性东西的一种高效枚举