提高组贪心专题做题记录

提高组贪心专题做题记录

A [NOIP2012 提高组] 国王游戏

考虑采用邻项交换法求解。考虑两个相邻的大臣 \(x,y\),什么时候 \(x\)\(y\) 优。那么假设 \(x\) 之前大臣左手数字乘积为 \(S\),则两种方案对应的权值应该是 \(\max\{\dfrac{S}{b_x},\dfrac{Sa_x}{b_y}\}\)\(\max\{\dfrac{S}{b_y},\dfrac{Sa_y}{b_x}\}\)。假设 \(x\) 在前更优,则应该有不等式:

\[\max\{\dfrac{S}{b_x},\dfrac{Sa_x}{b_y}\} <\max\{\dfrac{S}{b_y},\dfrac{Sa_y}{b_x}\} \]

化简得:

\[\max\{b_y,a_xa_y\}<\max\{b_x,a_yb_y\} \]

按照该不等式作为排序依据排序即可。最后高精度求出答案即可。

^B 皇后游戏

首先按照正常方法去推式子。依然考虑邻项交换法。首先需要知道 \(c_i\) 的本质是 \(\max\limits_{1\le k\le i}\{\sum\limits_{j=1}^ka_j+\sum\limits_{j=k}^{i}b_j\}\),然后考虑相邻两个大臣 \(x,y\),假设现在其放置位置为 \(i,i+1\)

考虑 \(x\) 在前的情况,在 \(i-1\) 处我们应该求出了上式的一个最大值 \(mx\) 和当 \(k=i-1\) 时上式的值 \(sum\)。那么此时我们再求出 \(k=i\) 时的值并取 \(\max\) 即可。因此此时 \(c_x\) 应该等于 \(\max\{mx,sum+a_x-b_{i-1}\}\)。同理可得 \(c_y=\max\{mx,sum+a_x-b_{i-1},sum+a_x+a_y-b_x-b_{i-1}\}\)

那么 \(y\) 在前的情况也是同理。所以我们可以得出如下不等式:

\[\max\{mx,sum+a_x-b_{i-1},sum+a_x+a_y-b_x-b_{i-1}\}<\max\{mx,sum+a_y-b_{i-1},sum+a_x+a_y-b_y-b_{i-1}\} \]

我们实际上可以先不考虑 \(mx\),因为如果要取 \(mx\) 的话两者换不换无所谓。所以化简后可得:

\[\min\{a_x,b_y\}<\min\{a_y,b_x\} \]

以此作为排序依据贪心。不过会发现交上去只有 \(80\) pts。原因是因为它其实是假的。此题的难点也在于此。

考虑邻项交换法所需要的比较函数 \(<\) 需要满足的条件,实际上是如下四个:

  1. 非自反性:\(x\not< x\)
  2. 非对称性:\(x<y\Rightarrow y\not <x\)
  3. 传递性:\(x<y,y<z\Rightarrow x<z\)
  4. 不可比性的传递性:\(x\not< y,y\not <x,y\not<z,z\not<y\Rightarrow x\not <z,z\not <x\)

实际上上述比较方式是不满足不可比性的传递性的。那么考虑修正,实际上问题只出现在 \(\min\{a_x,b_y\}=\min\{a_y,b_x\}\) 的时候,我们没有给它加上额外的比较条件,考虑到此时将 \(a\) 较小的放在前面一定更优,所以将这个判断加上。现在的比较函数就满足了所有条件,即可通过本题。

C [JXOI2017] 加法

考虑二分答案,然后考虑怎样 check。我们可以求出当前每一个数至少要被增加的次数,也就是至少要被多少个区间选中。然后从左边开始贪心,每一次选出还没有被选的、包含了当前节点的、右端点最远的区间,显然这样一定最优。

考虑如何维护,包含当前节点的限制可以扫描线解决,然后动态维护右端点的排序可以用优先队列。最后我们还需要动态维护 \(A\) 数组的信息来看当前需不需要选区间,用树状数组维护一下即可。

D 加工生产调度

与 B 题一模一样。采用邻项交换法甚至可以使前半部分证明更简洁。

E [NOIP2018 提高组] 赛道修建

仍然考虑二分答案。现在考虑怎样判定长度是否合法。我们在树上进行 DFS,每一个点给它的父亲传上去一条链,然后再父亲处将这些链进行合并,使得长度大于等于 \(mid\)(如果已经大于等于 \(mid\) 直接计入答案即可)。在剩下的链中取最大的上传给父亲即可。显然这个贪心是具有正确性的。

现在的问题就是合并链,我们既要保证合并的链数最多,又要保证剩下的链最大值尽可能大,所以考虑从小到大贪心,每一次二分找出与之匹配的链即可。这样剩下的链一定是最大的。

F [JOI 2022 Final] 让我们赢得选举

首先贪心去想可以得到这样一个策略:每一次演讲一定是所有人同时在一个地方演讲,并且在全部 \(k\) 次演讲中,前 \(r\) 次全部讲了 \(B_i\) 小时,后面的全部讲了 \(A_i\) 小时。这样一定最优。

考虑先枚举这个 \(r\)。由于前 \(r\) 次每一次讲完都可以获得一个协作者,所以先讲的 \(B_i\) 要尽可能小才会更优,所以按照 \(B_i\) 升序排列。但是此时直接取前 \(r\)\(B\) 是片面的,因为这里面有可能放到后面的 \(A\) 中讲更优,但是一定不会不讲。换句话说,如果在新的序列上我们取 \(B_i\)\(B_j\) 作为前 \(r\) 次演讲中相邻的两次演讲,那么中间的 \((i,j)\) 一定是在后面讲 \(A\) 小时的时候讲,而绝对不可能不讲(因为不讲还不如讲 \(B\) 小时优)。

这个时候就可以考虑 dp 了,设 \(dp(i,j)\) 表示前 \(i\) 个州内选择了 \(j\) 次讲 \(B\) 个小时,所花费的最小时间。转移方程是简单的:

\[dp(i,j)=\min\{dp(k,j-1)+\dfrac{\sum\limits_{x=k+1}^{i-1}A_x}{r+1}+\dfrac{B_i}{j}\} \]

看似复杂度 \(O(n^3)\),实际上可以简单优化至 \(O(n^2)\),总复杂度就是 \(O(n^3)\) 了。

*G [省选联考 2020 B 卷] 丁香之路

发现题目的要求很像欧拉路,我们将 \(s\)\(i\) 之间连一条边,那么实际上就是要求图上存在一个欧拉回路。那么考虑欧拉回路的条件,即所有点度数都是偶数。那么我们找出所有度数为奇数的点,从小到大两两一对连边。但是注意到此时连边 \(x\to y\) 不是最优的选择,我们应该连 \(x\to x+1\to x+2\to\cdots\to y\),因为这样可以使更多点联通在一起,同时对答案贡献不变。

此时欧拉图的性质已经满足,但是还没有满足联通性。考虑并查集缩点,然后跑一个最小生成树,每一条边只连相邻的点。跑出最小生成树大小后乘二(因为每一条边要走两次),再加上前面求出的总和即为答案。

*H [NOIP2023] 双序列拓展

首先需要想到一个最简单的 \(O(nm)\) 的 dp 做法,设 \(dp(i,j)\) 表示序列 \(x\) 匹配到第 \(i\) 位、序列 \(y\) 匹配到第 \(j\) 位是否可行。我们可以根据 \(x_1\)\(y_1\) 的关系判断出最后每一位上是什么关系,然后以此进行 dp。在这里我们只考虑 \(x_i<y_i\) 的情况。那么如果对于当前的 \(x_i<y_j\),则有转移方程 \(dp(i,j)=dp(i-1,j)\lor dp(i,j-1)\lor dp(i-1,j-1)\);否则 \(dp(i,j)=0\)。最后答案就是 \(dp(n,m)\)

考虑这个 dp 的实质。假如构造出一张网格图,令 \(p(i,j)=[x_i<y_j]\),那么上面 dp 的实质就是让我们从左上角走下、右、右下方向走一条只含 \(1\) 的路径到右下角。

然后我们考虑题目中给出的特殊性质。假如 \(\min\{x_i\}\ge \min\{y_i\}\),则必有 \(x_i\ge \min\{y_i\}\),于是 \(\min\{y_i\}\) 对应的那一行就全部是 \(0\),自然无解。对于 \(\max\{x_i\}\ge\max\{y_i\}\) 同理。特判掉这两种情况后我们发现,一定会有 \(\min\{x_i\}<y_i,x_i<\max\{y_i\}\) 了,也就是说,在特殊性质 1 中,我们网格图中第 \(n\) 列和第 \(m\) 行一定都是 \(1\)。因此我们的网格图就可以缩小一格。接下来我们进行同样的操作,如果 \(\min\{x_i\}\ge \min\{y_i\}\)\(\max\{x_i\}\ge\max\{y_i\}\) 的话一定无解,否则一定可以找到一行或一列,满足这一行或一列上全都是 \(1\),进而可以继续缩小网格,直到缩小到左上角即代表有解。根据贪心,单次缩小网格一定是不劣的。

那么对于总体来讲,我们依然可以找出 \(\min\{x_i\}\)\(\max\{y_i\}\) 的位置,此时除了这两个位置以外,整张网格被划分为了四个部分,我们需要从左上角走到这两个位置,再从这两个位置走到右下角。那么实际上和上面的思路是一致的,分别跑两次去缩小网格,看能否到左上角和右下角即可。复杂度 \(O(q(n+m))\)

^I [NOIP2012 提高组] 疫情控制

md 这个题让我认识到了贪心的险恶——你永远不知道什么数据可以 hack 掉你。

思路比较简单,我们先二分答案。然后接下来让每个点尽可能向上跳,最多跳到根节点的儿子处。现在有一些子树没有满足要求,刚才我们要求每个点最多跳到根节点的儿子处,因此有一些点会剩下一些剩余的时间没有用,我们再用这点时间取填上那些尚未满足要求的子树即可。

难点就在于怎么填这些子树。首先我们找到还可以挪动的自由点,需要保证它走到根节点后还有剩余时间,把这样的点存到 set 里;否则的话这个点就在这里驻扎了,打一个标记。接下来 DFS 一边整棵树,将标记上传(也就是看当前节点的子树内的所有叶子是否都满足要求了)。

再回看刚才 set 中的点,如果该点对应的子树尚未满足要求,且走到根节点后的剩余时间不足够走回来,那么这个点一定就在这里驻扎\(^{[1]}\)。现在剩下的 set 中的点就是一定可以自由挪动的点。此时子树尚未满足要求的就是待匹配的节点,我们将自由挪动的点按剩余时间递增排序,每一个点找到它能匹配的所需时间最大的节点匹配。根据贪心策略,这样做一定最优。

然后看待匹配点能否全部匹配上即可。复杂度 \(O(n\log n\log W)\)

\(^{[1]}\):证明如下:由于该点无法从当前的节点到达根节点再返回,所以如果它驻扎在根节点的其它儿子,只能驻扎在一个到根节点的距离小于当前节点到根节点的距离的节点。但是该点驻扎的那个节点也可以让剩余时间比当前节点多的点去驻扎,并且这样还更优。因此不如让剩余时间多的节点去驻扎,而自己留在当前节点即可。

^J [CF1935E] Distance Learning Courses in MAC

首先我们需要发现一些性质:

  • 对于一个 \([l_i,r_i]\),我们可以将它们在二进制下相同的前缀删去,并直接将其加入答案。
  • 对于一个 \([l_i,r_i]\),如果它们在第 \(j\) 位上不同,那么答案中要么第 \(j\) 位上是 \(1\),要么 \(0\sim j-1\) 位上全是 \(1\)

然后我们就可以开始贪心了。首先根据第一条性质算出当前已经知道的答案,接下来对剩下的部分从高位往低位贪心,如果这一位上有至少一个可以自由选择的 \(1\) 且总共有至少 \(2\)\(1\) 的话,我们就可以让 \(0\sim j\) 的每一位上都是 \(1\),然后直接输出即可;否则,如果这一位上有 \(1\) 的话,这一位上一定可以放 \(1\),最后如果没有 \(1\) 的话就只能放 \(0\) 了。前缀和维护 \(1\) 的个数和可自由选择的 \(1\) 的个数即可,复杂度 \(O(n\log V)\)

posted @ 2024-11-13 16:38  UKE_Automation  阅读(14)  评论(0编辑  收藏  举报