二分答案和三分入門



首先......我是一個很菜很菜的萌新,所以這篇文章寫得很詳細,有很多我自己的口水話方便我理解,請各位謹慎食用qwq
以前在網上找過很多介紹二分的博客,但都感覺對萌新不太友好,反正我當時連跳石頭都沒看懂,所以決定自己寫一篇!其中有我的想法,也借鑒了書里的很多內容,感謝lyd。

二分答案,顧名思義,就是對我們所需要的答案進行二分,對我們要求的值進行二分。
二分的基礎用法是在單調序列或者單調函數當中查找,當答案具有單調性,我們就可以采用二分來計算,當然還有三分,在后面我會詳細講到

整數集合上的二分

在單調遞增序列a中查找>=x的數當中最小的一個

while(l<r)
{
int mid=(l+r)>>1;
if(a[mid]>=x) r=mid; //普適模板:if(check()) r=mid;else l=mid+1;,下同。 
else l=mid+1;
}
return a[l];

 

在單調遞增序列a中查找<=x的數當中最大的一個

while(l<r)
{
int mid=(l+r+1)>>1;
if(a[mid]<=x) l=mid;
else r=mid-1;    
} 
return a[l];

 

根據以上兩種代碼形式 可以總結出二分的兩種常用形式
1.r=mid,l=mid+1,取中間值的時候,mid=(l+r)>>1;
2.l=mid,r=mid-1,取中間值的時候,mid=(l+r+1)>>1;

注意
1.如果不對mid的取法進行區分,可能會造成出錯的情況,在平時的練習當中,希望大家能注意選擇,我不再贅述,《進階指南》里面講得很詳細啦。
2.在二分當中,我們采用的是右移運算而不是除法,是因為右移運算是向下取整的,但除法向0取整。

終止條件:l==r 也就是答案所在的位置啦

實數域上的二分

實數域會方便很多,具體兩種方法。

1.給出精度eps 以l+eps<r為條件

while(l+eps<r)
{
//自己寫啦!
}

2.暴力循環100次 完全不用擔心不夠 2^100已經超過了int類型~
for(int i=0;i<100;i++)
{
//自己寫.jpg
}

關於二分的知識點大概就是上面這些,但是大家在寫代碼的時候一定要注意各種邊界條件,比如說l和r之間可不可以取等號,又或者mid是+1,-1還是不加不減。
我個人感覺二分當中的坑點很多,反正我經常因為各種亂七八糟的邊界條件debug老半天,肯定是編譯器的鍋!可能我還是比較菜對題目/模板的理解不夠深......

下面給出兩道練習題
洛谷P1873砍樹 題解(附帶原OJ鏈接)

洛谷P2678跳石頭(NOIP2015) 題解(附帶原OJ鏈接)

關於三分

三分,顧名思義就是分成三份,它主要用於求單峰函數的極值。
單峰函數,就是一個有極大值或者極小值的函數。
如果有極大值,那么極大值的左邊是單調遞增,右邊單調遞減;
如果有極小值,那么極小值的左邊是單調遞減,右邊是單調遞增。
其實我腦袋里面已經自動腦補了一個二次函數了......
(但兩者不能划等號哦!二次函數是單峰函數,但單峰函數中僅僅是包含了二次函數)

關於單峰函數求極值的分析

以一個有極大值的單峰函數為例(如圖所示)
若此函數有縱坐標y1<y2,那么它橫坐標的情況就是兩種
1.x1和x2都在極大值的左邊,並且x1<x2
2.x1在極大值的左邊,x2在極大值的右邊
通過分析,我們可以發現,x1總在極大值的左邊。
若此函數有縱坐標y1>y2,那么它橫坐標的情況也是兩種。
1.x1和x2都在極大值的右邊,並且x1<x2(感謝我の學長兼男神cjrhahahahaha指正此處 應為x1<x2 ovo)
2.x1在極大值的左邊,x2在極大值的右邊
通過分析,我們可以發現,x2總在極大值的右邊。
根據以上兩種操作,我們可以不停進行三分,直到找到極大值,對於有極小值的單峰函數也是同一個道理。

放兩張圖在這里,大家自行理解吧......

針對有極大值,且有y1<y2的單峰函數

針對有極小值,且有y1>y2的單峰函數。

qwq三分的知識其實比起二分更簡單易懂,因為它能解決的題目范圍更狹窄,但需要較強的數學思維,在題目中
能夠找出單峰函數的思想。 二分只是一個簡單的模板,如果運用到具體的問題當中,要先理清楚這道題有沒有二分思想,
同時呢,我認為二分當中的核心應該是check()函數。

下面給出一道題

洛谷P1873 傳送帶(SCOI2010) 題解(附原OJ鏈接)

二分的題解就到這里了,很感慨。第一次接觸二分我還是一個普及組萌新時根本就看不懂跳石頭,甚至完全無法理解......

事實證明,成長的道路上荊棘滿布,但只要我們勇敢前行,就沒有無法克服的艱難險阻!


免責聲明!

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



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