二分法
二分法有兩種,二分查找和二分答案。
二分查找
整數二分
整數二分的實質不在於單調性,而是看區間能否划分為兩塊,使得一塊滿足某種性質,而另一塊不滿足。
1.查找紅色區域最后的值(滿足條件的最后一個值):
check(mid):
1. true -> [mid, R]; --- l = mid
2. false -> [L, mid - 1]; --- r = mid - 1
2.查找藍色區域第一個值(滿足條件的第一個值):
check(mid):
1. true -> [L, mid]; --- r = mid
2. false -> [mid + 1, R]; --- l = mid + 1
二分查找想不出的話可以畫一畫圖,確定一下兩個分段。
二分查找模板:
bool check (int x) {/* ... */} // 檢查x是否滿足某個條件
// 區間[l, r]被划分為[l, mid]和[mid+1, r]:(滿足條件的第一個元素)
int bsearch_1 (int l, int r) {
while (l < r) {
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
// 區間[l, r]被划分為[l, mid-1]和[mid, r]:(滿足條件的最后一個元素)
int bsearch_2 (int l, int r) {
while (l < r) {
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
浮點數二分
bool check (double x) {/* ... */} // 檢查x是否滿足某個條件
double bsearch_3 (double l, double r) {
const double eps = 1e-6; // eps表示精度,取決於題目的精度要求
while (r - l > eps) {
double mid = r + l >> 1;
if (check(mid)) r = mid; // r和l可互換,取決於題目要求
else l = mid;
}
return l;
}
二分答案
根據答案的單調性(可滿足性)把答案所取范圍二分,每次取中間判斷是否可以滿足題目要求,滿足則記錄當前數值,直至二分完畢,則記錄的值為二分答案值。
例題: