From 5333cc02bb3de7f1b8a0f955069a71930e0acc72 Mon Sep 17 00:00:00 2001 From: Trisolaris HD <36555123+TrisolarisHD@users.noreply.github.com> Date: Tue, 26 Mar 2019 20:35:26 +0800 Subject: [PATCH] Update binary.md --- docs/basic/binary.md | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/docs/basic/binary.md b/docs/basic/binary.md index e231048a..3036396a 100644 --- a/docs/basic/binary.md +++ b/docs/basic/binary.md @@ -10,7 +10,7 @@ 在二分搜索过程中,每次都把查询的区间减半,因此对于一个长度为 $n$ 的数组,至多会进行 $O(\log n)$ 次查找。 -```c++ +```cpp int binary_search(int start, int end, int key) { int ret = -1; // 未搜索到数据返回-1下标 int mid; @@ -59,15 +59,14 @@ int binary_search(int start, int end, int key) { 解题的时候往往会考虑枚举答案然后检验枚举的值是否正确。如果我们把这里的枚举换成二分,就变成了“二分答案”。 -来看一看一道例题 [Luogu P1873 砍树](https://www.luogu.org/problemnew/show/P1873),我们可以从 1 到 1000000000(10 亿)来枚举答案,但是这种朴素写法肯定拿不到满分,因为从 1 跑到 10 亿太耗时间。我们可以对答案进行 1 到 10 亿的二分,其中,每次都对其进行检查可行性(一般都是使用贪心法)。 **这就是二分答案。** +来看一看一道例题 [Luogu P1873 砍树](https://www.luogu.org/problemnew/show/P1873),我们可以在 1 到 1000000000(10 亿)中枚举答案,但是这种朴素写法肯定拿不到满分,因为从 1 跑到 10 亿太耗时间。我们可以对答案进行 1 到 10 亿的二分,其中,每次都对其进行检查可行性(一般都是使用贪心法)。 **这就是二分答案。** 下面就是例题的参考答案。 -```c++ +```cpp int a[1000005]; int n, m; -bool check(int k) //检查可行性,k为锯片高度 -{ +bool check(int k) { //检查可行性,k为锯片高度 long long sum = 0; for (int i = 1; i <= n; i++) //检查每一棵树 if (a[i] > k) //如果树高于锯片高度 @@ -76,8 +75,7 @@ bool check(int k) //检查可行性,k为锯片高度 } int find(int x) { int l = 1, r = 1000000001; //因为是左闭右开的,所以10亿要加1 - while (l + 1 < r) //如果两点不相邻 - { + while (l + 1 < r) { //如果两点不相邻 int mid = (l + r) / 2; //取中间值 if (check(mid)) //如果可行 l = mid; //升高锯片高度 @@ -114,29 +112,29 @@ int main() { ## 三分法 -```c++ -mid = left + (right - left >> 1); -midmid = mid + (right - mid >> 1); // 对右侧区间取半 -if (cal(mid) > cal(midmid)) - right = midmid; +```cpp +lmid = left + (right - left >> 1); +rmid = lmid + (right - lmid >> 1); // 对右侧区间取半 +if (cal(lmid) > cal(rmid)) + right = rmid; else - left = mid; + left = lmid; ``` 三分法可以用来查找凸函数的最大(小)值。 画一下图好理解一些(图待补) -- 如果 `mid` 和 `midmid` 在最大(小)值的同一侧: +- 如果 `lmid` 和 `rmid` 在最大(小)值的同一侧: 那么由于单调性,一定是二者中较大(小)的那个离最值近一些,较远的那个点对应的区间不可能包含最值,所以可以舍弃。 - 如果在两侧: 由于最值在二者中间,我们舍弃两侧的一个区间后,也不会影响最值,所以可以舍弃。 ## 分数规划 -分数规划是这样一类问题,每个物品有两个代价 $c_i$ , $d_i$ ,要求通过某种方式选出若干个,使得 $\frac{\sum{c_i}}{\sum{d_i}}$ 最大或最小。 +分数规划是这样一类问题,每个物品有两个属性 $c_i$ , $d_i$ ,要求通过某种方式选出若干个,使得 $\frac{\sum{c_i}}{\sum{d_i}}$ 最大或最小。 -经典的例子是 最优比率环、最优比率生成树 等等。 +经典的例子有 最优比率环、最优比率生成树 等等。 ### 二分法 @@ -170,4 +168,4 @@ $$ ### Dinkelbach 算法 -Dinkelbach 算法是每次用上一轮的答案当做新的 $L$ 来输入,不断地迭代,直至答案收敛。 +Dinkelbach 算法的大概思想是每次用上一轮的答案当做新的 $L$ 来输入,不断地迭代,直至答案收敛。 -- 2.11.0