Loading .github/pull_request_template.md +5 −2 Original line number Diff line number Diff line Loading @@ -2,8 +2,11 @@ - 请在 commit 的时候写比较有意义的 commit message - 请给 PR 起比较有意义的标题。 - 关于同一类尚未合并的 PR 修改请直接在对应的 fork / 分支中进行,除非已有的内容已被合并需要修改,否则**不要多开 PR** 。 - 请在 PR 之前检查一下您的 PR 是否存在以下常见问题:(确认无问题后请将选项打钩 / 填为 `[x]`) * [ ] 您的 MD 代码的书写格式,包括但不限于 **中文与英文之间、中文与阿拉伯数字、中文与 LaTeX 公式之间要有一个半角空格**,特别地,在中文全角符号与英文、阿拉伯数字、LaTeX 公式之间,**不需要**半角空格。(这个可以使用自动化工具辅助,比如 https://github.com/baurine/vscode-pangu) * [ ] 请务必确保您的文档中引用的**外链**图片已经全部转存到了**本库内**对应的`images`文件夹中(防止触发某些网站的防盗链),并已全部处理成了`MD文档名称+编号`的形式(可参考已有文档中图片的处理方式) * [ ] 请确保您的文档中的引用链接的稳定性,**不推荐**引用**自建**服务(如OJ)中的资源(如题目) * [ ] 对于 LaTeX 公式,请注意常见的问题,**一定要使用** `$\log$`、`$\min$`、`$\max$`、`$\gcd$` 等,而非 `$log$`、`$min$`、`$max$`、`$gcd$`。对于最小公倍数,请使用 `$\operatorname{lcm}$` 而非 `$lcm$`,省略号请使用 `$\cdots$`,叉乘请使用 `$\times$`,点乘请使用 `$\cdot$`。 * [ ] 所有公式中的希腊字母等特殊符号,请不要使用输入法的插入特殊符号功能,而应该使用对应的 LaTeX 公式符号。如 phi 大多数情况下应该使用 `$\varphi$` 而不是 `$\phi$`。 * [ ] 行间公式前后各要有一行空行。 Loading .travis.yml +0 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ script: - mkdocs build -v - find ./site -type f -name '*.html' -exec node --max_old_space_size=512 ./scripts/render_math.js {} \; - npx gulp minify - docker build -t oi-wiki:latest . - set +e deploy: provider: pages Loading README.md +1 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ # 欢迎来到 **OI Wiki**! [](https://travis-ci.org/24OI/OI-wiki) [](https://github.com/24OI/OI-wiki) [](https://github.com/24OI/OI-wiki) [](https://status.oi-wiki.org/) [](https://t.me/OIwiki) [](https://jq.qq.com/?_wv=1027&k=5EfkM6K) Loading docs/basic/binary.md +20 −22 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) //如果树高于锯片高度 Loading @@ -76,13 +75,12 @@ 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; //升高锯片高度 else r = mid; //否则降低叶片高度 r = mid; //否则降低锯片高度 } return l; //返回左边值 } Loading Loading @@ -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}}$ 最大或最小。 经典的例子是 最优比率环、最优比率生成树 等等。 经典的例子有 最优比率环、最优比率生成树 等等。 ### 二分法 Loading Loading @@ -170,4 +168,4 @@ $$ ### Dinkelbach 算法 Dinkelbach 算法是每次用上一轮的答案当做新的 $L$ 来输入,不断地迭代,直至答案收敛。 Dinkelbach 算法的大概思想是每次用上一轮的答案当做新的 $L$ 来输入,不断地迭代,直至答案收敛。 docs/basic/bubble-sort.md 0 → 100644 +23 −0 Original line number Diff line number Diff line 冒泡排序是一种稳定的排序方法。 以升序为例,冒泡排序每次检查相邻两个元素,如果前面的元素大于后面的元素,就将相邻两个元素交换。当没有相邻的元素需要交换时,排序就完成了。 不难发现,我们最多需要扫描 $n$ 遍数组才能完成排序。 ```cpp void bubble_sort() { for (int i = 1; i <= n; i++) { bool flag = false; for (int j = 1; j < n; j++) if (a[j] > a[j + 1]) { flag = true; int t = a[j]; a[j] = a[j + 1]; a[j + 1] = t; } if (!flag) break; //如果没有执行交换操作,说明数列已经有序 } } ``` 在序列完全有序时,该算法只需遍历一遍数组,不用执行任何交换操作,时间复杂度为 $O(n)$ 。在最坏情况下,冒泡排序要执行 $\frac{(n-1)n}{2}$ 次交换操作,时间复杂度为 $O(n^2)$ 。在平均情况下,冒泡排序的时间复杂度也是 $O(n^2)$ 。 No newline at end of file Loading
.github/pull_request_template.md +5 −2 Original line number Diff line number Diff line Loading @@ -2,8 +2,11 @@ - 请在 commit 的时候写比较有意义的 commit message - 请给 PR 起比较有意义的标题。 - 关于同一类尚未合并的 PR 修改请直接在对应的 fork / 分支中进行,除非已有的内容已被合并需要修改,否则**不要多开 PR** 。 - 请在 PR 之前检查一下您的 PR 是否存在以下常见问题:(确认无问题后请将选项打钩 / 填为 `[x]`) * [ ] 您的 MD 代码的书写格式,包括但不限于 **中文与英文之间、中文与阿拉伯数字、中文与 LaTeX 公式之间要有一个半角空格**,特别地,在中文全角符号与英文、阿拉伯数字、LaTeX 公式之间,**不需要**半角空格。(这个可以使用自动化工具辅助,比如 https://github.com/baurine/vscode-pangu) * [ ] 请务必确保您的文档中引用的**外链**图片已经全部转存到了**本库内**对应的`images`文件夹中(防止触发某些网站的防盗链),并已全部处理成了`MD文档名称+编号`的形式(可参考已有文档中图片的处理方式) * [ ] 请确保您的文档中的引用链接的稳定性,**不推荐**引用**自建**服务(如OJ)中的资源(如题目) * [ ] 对于 LaTeX 公式,请注意常见的问题,**一定要使用** `$\log$`、`$\min$`、`$\max$`、`$\gcd$` 等,而非 `$log$`、`$min$`、`$max$`、`$gcd$`。对于最小公倍数,请使用 `$\operatorname{lcm}$` 而非 `$lcm$`,省略号请使用 `$\cdots$`,叉乘请使用 `$\times$`,点乘请使用 `$\cdot$`。 * [ ] 所有公式中的希腊字母等特殊符号,请不要使用输入法的插入特殊符号功能,而应该使用对应的 LaTeX 公式符号。如 phi 大多数情况下应该使用 `$\varphi$` 而不是 `$\phi$`。 * [ ] 行间公式前后各要有一行空行。 Loading
.travis.yml +0 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ script: - mkdocs build -v - find ./site -type f -name '*.html' -exec node --max_old_space_size=512 ./scripts/render_math.js {} \; - npx gulp minify - docker build -t oi-wiki:latest . - set +e deploy: provider: pages Loading
README.md +1 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ # 欢迎来到 **OI Wiki**! [](https://travis-ci.org/24OI/OI-wiki) [](https://github.com/24OI/OI-wiki) [](https://github.com/24OI/OI-wiki) [](https://status.oi-wiki.org/) [](https://t.me/OIwiki) [](https://jq.qq.com/?_wv=1027&k=5EfkM6K) Loading
docs/basic/binary.md +20 −22 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) //如果树高于锯片高度 Loading @@ -76,13 +75,12 @@ 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; //升高锯片高度 else r = mid; //否则降低叶片高度 r = mid; //否则降低锯片高度 } return l; //返回左边值 } Loading Loading @@ -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}}$ 最大或最小。 经典的例子是 最优比率环、最优比率生成树 等等。 经典的例子有 最优比率环、最优比率生成树 等等。 ### 二分法 Loading Loading @@ -170,4 +168,4 @@ $$ ### Dinkelbach 算法 Dinkelbach 算法是每次用上一轮的答案当做新的 $L$ 来输入,不断地迭代,直至答案收敛。 Dinkelbach 算法的大概思想是每次用上一轮的答案当做新的 $L$ 来输入,不断地迭代,直至答案收敛。
docs/basic/bubble-sort.md 0 → 100644 +23 −0 Original line number Diff line number Diff line 冒泡排序是一种稳定的排序方法。 以升序为例,冒泡排序每次检查相邻两个元素,如果前面的元素大于后面的元素,就将相邻两个元素交换。当没有相邻的元素需要交换时,排序就完成了。 不难发现,我们最多需要扫描 $n$ 遍数组才能完成排序。 ```cpp void bubble_sort() { for (int i = 1; i <= n; i++) { bool flag = false; for (int j = 1; j < n; j++) if (a[j] > a[j + 1]) { flag = true; int t = a[j]; a[j] = a[j + 1]; a[j + 1] = t; } if (!flag) break; //如果没有执行交换操作,说明数列已经有序 } } ``` 在序列完全有序时,该算法只需遍历一遍数组,不用执行任何交换操作,时间复杂度为 $O(n)$ 。在最坏情况下,冒泡排序要执行 $\frac{(n-1)n}{2}$ 次交换操作,时间复杂度为 $O(n^2)$ 。在平均情况下,冒泡排序的时间复杂度也是 $O(n^2)$ 。 No newline at end of file