Loading docs/basic/greedy.md +37 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,43 @@ 有些题的排序方法非常显然,如[LG1209](https://www.luogu.org/problemnew/show/P1209)就是将输入数组差分后排序模拟求值。 然而有些时候很难直接一下子看出排序方法,比如[LG1080](https://www.luogu.org/problemnew/show/P1080)就很容易凭直觉而错误地以a或b为关键字排序,过样例之后提交就发现 WA 了 QAQ。一个 ~~众所周知的~~ 常见办法就是尝试交换数组相邻的两个元素来**推导**出正确的排序方法。我们假设这题输入的俩个数用 `struct { int a, b; } v[n];` 来保存,用 `m` 表示 `i` 前面所有的 `a` 的乘积,那么第 `i` 个大臣得到的奖赏就是 `m / v[i].b`,第 `i + 1` 个大臣得到的奖赏就是 `m * v[i].a / v[i + 1].b`。如果我们交换第 `i` 个大臣与第 `i + 1` 个大臣的位置,那么第 `i + 1` 个大臣得到的奖赏就是 `m / v[i + 1].b`,第 `i + 1` 个大臣得到的奖励就是 `m * v[i + 1].a / v[i].b`。如果交前更优当且仅当 `max(m / v[i].b, m * v[i].a / v[i + 1].b) < max(m / v[i + 1].b, m * v[i + 1].a / v[i].b)`,提取出相同的 `m` 并约分得到 `max(1 / v[i].b, v[i].a / v[i + 1].b) < max(1 / v[i + 1].b, v[i + 1].a / v[i].b)`,然后分式化成整式得到 `max(v[i + 1].b, v[i].a * v[i].b) < max(v[i].b, v[i + 1].a * v[i + 1].b)`,于是我们就成功得到排序函数了! 然而有些时候很难直接一下子看出排序方法,比如[LG1080](https://www.luogu.org/problemnew/show/P1080)就很容易凭直觉而错误地以a或b为关键字排序,过样例之后提交就发现 WA 了 QAQ。一个 ~~众所周知的~~ 常见办法就是尝试交换数组相邻的两个元素来**推导**出正确的排序方法。我们假设这题输入的俩个数用一个结构体来保存 ```c++ struct { int a, b; } v[n]; ``` 用 $m$ 表示 $i$ 前面所有的 $a$ 的乘积,那么第 $i$ 个大臣得到的奖赏就是 $$\frac{m} {v[i].b}$$ 第 $i + 1$ 个大臣得到的奖赏就是 $$\frac{m \cdot v[i].a} {v[i + 1].b}$$ 如果我们交换第 $i$ 个大臣与第 $i + 1$ 个大臣的位置,那么第 $i + 1$ 个大臣得到的奖赏就是 $$\frac{m} {v[i + 1].b}$$ 第 $i + 1$ 个大臣得到的奖励就是 $$\frac{m \cdot v[i + 1].a} {v[i].b}$$ 如果交前更优当且仅当 $$\max {\frac{m} {v[i].b}, \frac{m \cdot v[i].a} {v[i + 1].b}} < \max {frac{m} {v[i + 1].b}, \frac{m \cdot v[i + 1].a} {v[i].b}}$$ 提取出相同的 $m$ 并约分得到 $$\max{\frac{1} {v[i].b}, \frac{v[i].a} {v[i + 1].b}} < \max{\frac{1} {v[i + 1].b}, \frac{v[i + 1].a} {v[i].b}}$$ 然后分式化成整式得到 $$\max{v[i + 1].b, v[i].a \cdot v[i].b} < \max{v[i].b, v[i + 1].a \cdot v[i + 1].b}$$ 于是我们就成功得到排序函数了! ```c++ struct uv { Loading Loading
docs/basic/greedy.md +37 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,43 @@ 有些题的排序方法非常显然,如[LG1209](https://www.luogu.org/problemnew/show/P1209)就是将输入数组差分后排序模拟求值。 然而有些时候很难直接一下子看出排序方法,比如[LG1080](https://www.luogu.org/problemnew/show/P1080)就很容易凭直觉而错误地以a或b为关键字排序,过样例之后提交就发现 WA 了 QAQ。一个 ~~众所周知的~~ 常见办法就是尝试交换数组相邻的两个元素来**推导**出正确的排序方法。我们假设这题输入的俩个数用 `struct { int a, b; } v[n];` 来保存,用 `m` 表示 `i` 前面所有的 `a` 的乘积,那么第 `i` 个大臣得到的奖赏就是 `m / v[i].b`,第 `i + 1` 个大臣得到的奖赏就是 `m * v[i].a / v[i + 1].b`。如果我们交换第 `i` 个大臣与第 `i + 1` 个大臣的位置,那么第 `i + 1` 个大臣得到的奖赏就是 `m / v[i + 1].b`,第 `i + 1` 个大臣得到的奖励就是 `m * v[i + 1].a / v[i].b`。如果交前更优当且仅当 `max(m / v[i].b, m * v[i].a / v[i + 1].b) < max(m / v[i + 1].b, m * v[i + 1].a / v[i].b)`,提取出相同的 `m` 并约分得到 `max(1 / v[i].b, v[i].a / v[i + 1].b) < max(1 / v[i + 1].b, v[i + 1].a / v[i].b)`,然后分式化成整式得到 `max(v[i + 1].b, v[i].a * v[i].b) < max(v[i].b, v[i + 1].a * v[i + 1].b)`,于是我们就成功得到排序函数了! 然而有些时候很难直接一下子看出排序方法,比如[LG1080](https://www.luogu.org/problemnew/show/P1080)就很容易凭直觉而错误地以a或b为关键字排序,过样例之后提交就发现 WA 了 QAQ。一个 ~~众所周知的~~ 常见办法就是尝试交换数组相邻的两个元素来**推导**出正确的排序方法。我们假设这题输入的俩个数用一个结构体来保存 ```c++ struct { int a, b; } v[n]; ``` 用 $m$ 表示 $i$ 前面所有的 $a$ 的乘积,那么第 $i$ 个大臣得到的奖赏就是 $$\frac{m} {v[i].b}$$ 第 $i + 1$ 个大臣得到的奖赏就是 $$\frac{m \cdot v[i].a} {v[i + 1].b}$$ 如果我们交换第 $i$ 个大臣与第 $i + 1$ 个大臣的位置,那么第 $i + 1$ 个大臣得到的奖赏就是 $$\frac{m} {v[i + 1].b}$$ 第 $i + 1$ 个大臣得到的奖励就是 $$\frac{m \cdot v[i + 1].a} {v[i].b}$$ 如果交前更优当且仅当 $$\max {\frac{m} {v[i].b}, \frac{m \cdot v[i].a} {v[i + 1].b}} < \max {frac{m} {v[i + 1].b}, \frac{m \cdot v[i + 1].a} {v[i].b}}$$ 提取出相同的 $m$ 并约分得到 $$\max{\frac{1} {v[i].b}, \frac{v[i].a} {v[i + 1].b}} < \max{\frac{1} {v[i + 1].b}, \frac{v[i + 1].a} {v[i].b}}$$ 然后分式化成整式得到 $$\max{v[i + 1].b, v[i].a \cdot v[i].b} < \max{v[i].b, v[i + 1].a \cdot v[i + 1].b}$$ 于是我们就成功得到排序函数了! ```c++ struct uv { Loading