二分法

二分

二分顧名思義
其實就不斷的把東西分爲兩半
二分自古就有html

  • 一尺之棰,日取其半,萬世不竭 -----《莊子·雜篇·天下》

二分在數學中,也有應用,例如零點存在性定理ios

\(設y=f(x) 若是f(x)在 [a,b]上連續 且 f(a)*f(b)<0 則[a,b]之間存在零點\)學習

只須要經過不斷的二分就能夠找到零點ui

今天主要介紹兩種二分的應用
spa

二分查找

二分查找:是經過二分的方法來查找code

  • 好比在一個升序序列查找一個數是否存在
    假設一個升序
    1,5,8,9,11,20,33
    咱們要查找一個數爲1
    先將1與中間數9相比較,1比9小,那麼1爲必定在以9爲分割點,分紅的兩個區間的左區間[1,5,8]
    再將1與區間[1,5,8]的中間數5相比較,1小於5,那麼必定在以5爲分割點,分紅兩個區間的左區間[1]
    最後找到1

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(答案),判斷最終答案在左區間仍是右區間最終獲得答案

例題選講

進擊的奶牛

通常看見這種最大值的最小值也有可能用二分答案

首先咱們須要肯定具備單調性

求得相鄰兩頭牛最近距離得最大值,由於距離嘛,要麼長要麼短,短的變到長,具備單調性實錘

那範圍了?
最小值:能夠爲兩個隔間的最小距離
最大值:兩個相距最遠得隔間得差
很容易看出來
(稍微講下緣由,懂得同窗就日後看把

  • 緣由
    最小值應該容易理解吧,若是最小值比相鄰兩個隔間最小值還小,那根本不存在其餘隔間能放牛
    好比兩頭牛
    三個隔間座標
    1,3,9
    最小值爲2,若是此時你設最小值爲1,那根本不存在這樣一個答案
    既然是答案,那麼必定具備答案的性質,能有解

借用剛剛的例子最大值爲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]
此時就找到最近距離的最大值

回放一遍咱們模擬過程
判斷其答案是否知足題意,排除不知足的區間,留下知足的區間,最終找到最終答案

  • code
#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;
}

總結

二分查找
查找的關鍵字必定具備單調性
(若是二分對象無序,那麼須要排序,排序的學習筆記

二分答案

  1. 答案具備單調性
    2.找出答案的上下界(也就是最小值及最大值)
    3.經過二分排除非答案區間,在可能的答案種繼續二分

其實二分本質也是枚舉,在一種特殊具備單調性序列或其餘具備單調性東西的一種高效枚舉

相關文章
相關標籤/搜索