舉個例子,對於最大值最小的問題,二分求這個最小的最大值
這是一個題解的二分寫法,我發現好像大家都是這麼寫二分的 P3853 絕_塵的題解
while(l<=r) {
int mid=(l+r)>>1, k=0;
/*sentence code*/
if(k>t){
l=mid+1;
}
else{
r=mid-1;
ans=mid;
}
}
printf("%d",ans);
return 0;
本問題的二分的過程大約可以這麼形象的描述,對於遞增數列:
, , …, , , , …
及其以後的數值全部都符合題意,但是要求其中最小的值,也就是
對於此題,mid越大,k越小。使得 成立的mid是符合題意的。
而且要注意:即使 , 此時的mid也不一定就是ans
在這個代碼當中
- 當 時,就相當於當前的 處於區間
- 當 時,就相當於當前的 處於區間 , 也包含了最終結果
那麼就有個很顯然的問題:當mid恰好爲ans的時候,若 ,那麼右邊界 r 將到達 的左側
此時會發生什麼?我們可以看到此while循環只有一個出口:, 那麼此時只要能跳出循環,就能輸出正確答案 ,否則不可能輸出正確答案
那麼什麼情況下, 本循環後能跳出呢?這裏注意兩點:
- , 則下一步跳出
- 如果此後得到的mid再也無法符合題意,則ans的值將不變,隨着 l 和 r 的緊縮,最終將到達1的情況,並跳出循環
不得不說,這個ans的設置相當巧妙,我tm以前怎麼沒發現這種寫法
完
當然,這裏是一定能找到結果的二分,還有的二分是可能查不到結果的,等下再寫。