二分顧名思義
其實就不斷的把東西分爲兩半
二分自古就有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; }
二分查找
查找的關鍵字必定具備單調性
(若是二分對象無序,那麼須要排序,排序的學習筆記
二分答案
其實二分本質也是枚舉,在一種特殊具備單調性序列或其餘具備單調性東西的一種高效枚舉