二分寫法選講


二分寫法總結

眾所周知,二分是一種特別常用的求解答案的方式。無論是二分查找,還是二分答案,都通過二分思想把求解轉化成了判定。這樣就大大減少了思維難度,並大大減少了復雜度。但實現二分並不是我們想象的那樣簡單,實現二分的難點是判定函數的書寫以及二分循環的寫法,判定函數需要根據題目的類型不同具體類型具體分析。那么我們這篇隨筆就着重講解一下二分的寫法,以便讓大家拍對二分,拍熟二分。

本篇隨筆是功能型隨筆。默認讀者已經明白二分思想並能手寫二分,只是對二分到底該怎么寫,怎么避免死循環等問題尚有困惑,如果對二分還不了解的讀者,請先行補習二分。

  • 二分書寫的要點

二分有很多種寫法,如果翻看一篇二分題目的題解,我們會發現不同的AC代碼中二分寫的五花八門。但是他們的結果都是對的。那么,二分書寫的要點到底是什么呢?

首先,是循環條件。這個條件是二分書寫的重中之重,因為這個條件如果寫不對的話,就可能導致二分進行過程中無法退出循環。即導致死循環的情況,而這個條件也決定了二分進行過程中縮小解集范圍的書寫方式。

然后,是縮小方式。所謂縮小方式,就是縮小下一步要二分的區間,也就是把\(l,r\)的值變成\(mid\),但是這個變化暗藏殺機。如果和循環條件配合不好的話,非常容易直接死循環,或者造成\(mid\)上的答案取不到(假如答案就是這個\(mid\)的話就慘了)等后果。

最后,是退出條件。退出二分循環的條件一定要確定好,這樣才能確定答案的位置。並且也可以通過算法分析來避免死循環。

  • 我的二分寫法

注:我並不是在推銷自己的二分寫法,我覺得如果是一個已經有了一個成型二分寫法的選手來看本博客的話,學習到的東西約等於0。所以,為了面向更廣大的對二分書寫極為蒙圈的選手比如說我,在此介紹和推導我的二分寫法,如果各位看官覺得有理,就直接采納我的寫法吧。順手求推薦

我的二分循環模板大體是這樣:

模板1:

while(l<r)
{
	int mid=(l+r)>>1;
	if(check(mid))
		l=mid+1;
	else
		r=mid;
}

模板2:

while(l<r)
{
	int mid=(l+r+1)>>1;
	if(check(mid))
		l=mid;
	else
		r=mid-1;
}

是的,這是兩套寫法。注意是兩套寫法,而不是兩種寫法,這兩種寫法會有很大的區別。首先是區間的縮小上,左端點和右端點的移動就不一樣,其次,mid的取法也不一樣。那么,這兩種寫法到底有什么不同呢?

首先我們關注這個區間縮小上的不同,我們對一個mid值進行判斷的時候,如果它合法,那么就要根據題意左移或者右移區間,但是這個mid到底有沒有可能是答案呢?這要依題目而定,如果這個mid可能是答案,那么在移動區間的時候就要把這個mid值也包含進來,否則就要\(\pm 1\)

通過以上的敘述,我們再來關注第二點不同,mid的取值方式,假如我們的mid可能是答案,那么我們再次移動區間的時候,就可以直接除以2,因為這時的左移/右移區間時把mid已經包含進去了,所以無論最后區間縮小到什么程度(我們分析時一般認為最小區間只有兩個整數),都不會造成死循環,因為在最小情況下\(mid=\lfloor l+r\rfloor\)會得出一個確切值,我們就能通過對mid的check來確定答案是否是它。但是如果mid不可能是答案,縮小區間的時候需要\(\pm1\)的情況下,這么直接/2,取整之后會導致區間不會縮小,這樣就會造成死循環,對應的解決辦法是這樣:\(mid=\lfloor l+r+1\rfloor\)。這樣就保證了死循環情況絕對不會出現。

  • 實數二分

實數二分就不需要考慮上面那么多的問題,我們只需要考慮循環條件。其實也很簡單,因為我們二分的是實數,所以需要考慮精度損失的問題。那么我們的循環條件就應該是這個不能損失的精度,一般我們把eps(精度)定義成1e-5,個別題目需要更加精確,請大家具體分析。

實數二分還需要注意,這里的mid取的時候絕不能使用算數右移>>,因為這個右移是針對整數的(因為是位運算嘛!)

大概模板是這樣:

while(r-l>eps)
    {
        long double mid=(l+r)/2;
        if(check(mid))
            r=mid;
        else
            l=mid;
    }
  • 總結

二分方法千萬種,保證正確是首要。

函數正確二分炸,只剩退役路一條。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM