贪心做题记录-1

贪心做题记录-1

CF626G. Raffles

考虑在奖池中新增一个彩票新增的期望:设初始有 \(l\) 张,当前已有 \(c\) 张,获奖奖金为 \(p\),那么 \(\Delta E=\dfrac{p(c+1)}{c+1+l}-\dfrac{pc}{c+l}=\dfrac{pl}{(c+l)(c+l+1)}\)。发现对于一个奖池来说这个内容是单减的,因此可以直接贪心每次选择最大值。

接下来考虑修改的影响,以减少为例,显然选则每一张的期望都会增大,然而考虑原来的第 \(c+1\) 张新增的期望和修改后第 \(c+2\) 张新增的期望,发现两者分别为 \(\dfrac{pl}{(c+l)(c+1+l)}\)\(\dfrac{p(l-1)}{(c+l)(c+1+l)}\),发现期望减少了,因为原来的第 \(c+1\) 张不优,因此现在的第 \(c+2\) 张肯定不优。对于增加同理,所以每次修改我们最多修改一张彩票的贡献。将修改位置的最后一张彩票的贡献修改正确即可,对于之前贡献的修改不难看出可以进行整体操作,根据目前选择该奖池的彩票数直接推断出目前该奖池的贡献,然后可以直接修改,复杂度是 \(O((t+q)\log n)\) 的。

因为不能选择超过原有彩票的数量较难维护,不妨考虑在超过原有彩票时将贡献直接视作 \(0\),这样不影响答案并且相对好维护一些。

CF704D. Captain America

考虑根据题目给出的信息我们可以轻松推出每行每列的某个颜色的点的个数范围,为了让总代价最小,我们考虑让拥有较小代价的点尽可能多,于是我们考虑上下界网络流,对每一行每一列一个上下界表示选择的点数的范围,然后对于每一个点连接 \(x,y\),如果这条边有流量就说明选择了这个点,于是就是跑一遍有源汇上下界最大流。

CF708E. Student's Camp

首先容易直接计算出一边被破坏了 \(x\) 个格子的概率 \(P(x)={k\choose x}p^x(1-p)^{k-x}\),因为两边互不干扰,所以某一行被破坏到 \([l,r]\) 的概率是容易算出为 \(P(l-1)P(m-r)\)。一个 naive 的想法是直接 dp,令 \(f_{i,l,r}\) 表示第 \(i\) 行被破坏到仅剩 \([l,r]\) 时前 \(i\) 行连通的概率,转移只需要找到所有 \(l'\le r,r'\ge l\)\(f_{i-1,l',r'}\) 的和即可,利用二维前缀和可以做到 \(O(nm^2)\)

我们考虑优化,更具体的,我们考虑不计算所有符合转移条件的位置的概率和,而是计算所有位置的概率和减去不符合转移条件的位置的概率和,即

\[f_{i,l,r}=P(l-1)P(m-r)(\sum_{l'\le r'}f_{i-1,l',r'}-\sum_{l'\le r'<l}f_{i-1,l',r'}-\sum_{r<l'\le r'}f_{i-1,l',r'}) \]

于是我们可以考虑迅速维护中间的三个和式,分别记为 \(F(i-1),L(i-1,l),R(i-1,r)\)。我们关注到,\(F(i)\) 即为前 \(i\) 行连通的概率,因此只需要求出 \(F(n)\) 即可,并且 \(L,R\) 的形式高度对称,也就是说我们有 \(L(i,x)=R(i,m+1-x)\),所以我们下文只关注 \(L\) 的求法。

可以考虑维护一个 \(S(i,x)\) 表示所有右端点为 \(x\) 的位置的概率和,那么我们有 \(L(i,l)=\sum_{x<l}S(i,x)\),并且,我们发现 \(F(i)\) 就是所有 \(S\) 的和,于是我们只需要能够快速求出 \(S\) 就可以推出所有内容,考虑直接将 \(f\) 的转移式代入,我们有:

\[\begin{aligned}S(i,r)&=\sum_{l\le r}f_{i,l,r}\\&=\sum_{l\le r}P(l-1)P(m-r)(F(i-1)-L(i-1,l)-R(i-1,r))\\&=P(m-r)([F(i-1)-R(i-1,r)]\sum_{l\le r}P(l-1)-\sum_{l\le r}P(l-1)L(i-1,l))\end{aligned} \]

于是我们可以在 \(O(nm)\) 的复杂度内求得所有内容。

CF538H. Summer Dichotomy

考虑构造 \(n_1=\min_{1\le i\le n}r_i,n_2=\max_{1\le i\le n}l_i\),对于这样的构造分类讨论:

  1. 存在一个 \([l_i,r_i]\) 满足 \(n_1<l_i\le r_i<n_2\),此时显然无解。
  2. 所有 \([l_i,r_i]\) 两两有交,此时显然所有老师可以任意选择。
  3. 否则因为不存在无法选择的老师,则此时每位老师至少可以选择其中一个。

问题在于无法保证 \(t\le n_1+n_2\le T\)。考虑一个贪心的想法:\(n_1\) 变大必然导致一个老师无法选择,\(n_2\) 变小必然导致一个老师无法选择,因此 \(n_1\) 只会减小,\(n_2\) 只会变大。也就是在 \(n_1+n_2>T\) 时调整 \(n_1\)\(n_1+n_2<t\) 时调整 \(n_2\) 即可。于是我们得到了一组可能的可行解,接着跑一遍二分图染色检查即可,复杂度是 \(O(n+m)\) 的。

CF573E. Bear and Bowling

有一个贪心:每一次我们考虑所有未选择的数对答案的贡献,选择最大的那一个,然后不断更新其他剩余数的贡献,直到答案无法增加为止,最后得到的就是答案。通过实践发现这个贪心是对的,并且这个贪心的正确性是可以保证的。

考虑每个数的贡献都形如 \(ka_i+b\) 的形式,其中 \(k\) 是前面已经选择的数的个数加 \(1\)\(b\) 是后面所有数的和。那么选择一个数的影响就是对前面所有数的 \(b\) 增加 \(a_p\),后面所有数的 \(k\) 增加 \(1\)

Solution1

可以直接使用 KTT 维护从而做到超小常数 \(O(n\log^3n)\)

Solution2

也可以考虑用分块维护。更具体的,为了找到每个块内 \(ka_i+b\) 最大的数,对于每一个块,我们维护每一个块统一的 \(k,b\) 和单独的 \(f_i\),那么每个数的贡献就是 \(ka_i+b+f_i\),然后可以维护一个上凸包去求解,对于新选择的数所在的块暴力重构。这样每次查询在块内二分可以做到 \(O(n\sqrt{n}\log n)\)。但是考虑到每个块在重构之前的 \(k\) 单调不降,因此二分的斜率具有单调性,也就是说我们可以用单调队列将复杂度优化至 \(O(n\sqrt{n})\)

事实上 KTT 跑得是比分块快得多的。

CF1495E. Qingshan and Daniel

考虑到最先出完所有牌的一定是牌总数较少的那一组,我们将这一组记为 \(A\),剩下的那一组记为 \(B\),然后将所有连续且在同一组的记作同一段,那么最后一定形如 \(ABAB\cdots AB\)\(BABA\cdots BA\),对于第二种情况,找到第一次操作与其匹配的 \(A\),统计第一个 \(B\) 的贡献从后这个位置开始即可,不难证明对答案不产生影响。

考虑对于 \(A\) 的答案显然已知,只需要考虑 \(B\) 的答案,不难发现每一个 \(A\) 在后面都一定对应一个 \(B\) 的回应,不妨暴力扫两遍序列,同时维护有多少个 \(A\) 没有和 \(B\) 匹配,那么每遇到一个 \(A\),只需要将对应的牌数加入即可。而遇到 \(B\) 时考虑尽可能多的匹配即可,这样复杂度是 \(O(n)\) 的。

CF526G. Spiders Evil Plan

因为路径是可重的,所以 \(k\) 条路径显然可以得出一棵 \(2k\) 个叶子的树,考虑这些叶子都是原树上的叶子肯定更优。我们先忽略包含 \(x\) 的条件,则这个内容是套路的:首先考虑到一定存在一个最优方案使得选择了直径的其中一个端点,于是可以以两个端点均为根跑一次答案。因为直径的端点一定是叶子,那么我们就是要选除根外的 \(2k-1\) 个叶子,接下来分类讨论:

  • 当原树叶子结点个数比所需的叶子还要小,答案就是所有边的权值和。
  • 否则对原树进行带权长链剖分,然后按照所在链的边权和从大到小选择。容易证明这样次选出来的点一定和根节点连通。

考虑加入包含 \(x\) 的条件,那么无非是两种情况:

  1. 删去贡献最小的叶子并加入 \(x\) 所在的链。注意为了保证连通要加入这条链上方的所有未选择的边。
  2. 删去 \(x\) 所在链上方最近的一条被选择的链的后半段,然后加入 \(x\) 所在链上方的所有边。

虽然我们无法保证 \(2\) 操作得出的答案是连通的,但可以证明不连通时得到的答案一定不如 \(1\)。于是可以直接求解。注意到这道题进行的是带权重链剖分,因此不能直接跳链求解上面的内容,需要使用倍增,复杂度是 \(O(m\log n)\) 的。

CF1693E. Outermost Maximums

考虑肯定贪心的将每个位置覆盖成前缀最大值和后缀最大值中更小的那个,因为肯定优先处理比自己大的和外层的最大值,所以需要忽略值比自己大的值和相同的值的贡献,这样可以做到 \(O(n^2)\)

考虑给每一个位置一个标记,分为取前缀最大值、未确定和取后缀最大值。当我们枚举到一个值的时候,将所有位置初始化成未确定。接下来当枚举到一个更小的值的时候,如果一个未确定的标记在其最右位置的右侧,则肯定取后缀最大值更好,在其最左位置的左侧也同理取前缀最大值。而在最左位置右侧的前缀最大值标记因为相当于确定取到该值,将该位置视为当前值一同处理即可,对于在最右位置左侧的后缀最大值标记同理。

分析可以发现任何时刻一定一个前缀的标记为取前缀最大值,一个后缀的标记为取后缀最大值,中间的一段为未确定,于是可以维护这三个标记的分界线。对于每一个值,维护当前有多少个位置最终会取到这个值,将所有和累加即为答案。计 \([l,r]\) 为取未确定标记的位置的范围,那么根据当前值的出现的极小区间 \([L,R]\) 和其的位置关系分类讨论即可。用数组结构维护区间已操作位置的个数,复杂度是 \(O(n\log n)\)

CF1827E. Bus Routes

有一个显然的充要条件:原问题有解当且仅当存在一个点使得每个点到这个点都能通过至多一条路径到达。考虑如何找出这个点。

首先我们发现我们只需要判断叶子结点,因为叶子结点能够一步到达,则其到根路径上的所有点都能一步到达。我们先随意取一个点为根,记 \(\text{faz}(l)\)\(l\) 通过一步路径能到达的深度最浅的点。考虑如果存在两个点的 \(\text{faz}\) 不为祖先关系,那么显然无解,构造就是这两个叶子结点。否则我们选取深度最深的 \(\text{faz}\),以这个点为根再求一次 \(\text{faz}\),如果存在点的 \(\text{faz}\) 不为根,则显然无解,构造即为这个点和之前的 \(\text{faz}\) 为根节点的点,否则肯定有解。

证明是容易的:对于第一个无解证明显然,因为这两个叶子之间至少还要一条路径才能连通;对于有解也显然,因为我们找到了符合要求的点;对于第二个无解,考虑如果根就是叶子结点,那么说明没有和这个叶子相连的路径,构造显然符合;否则根不是叶子,那么考虑在原来的树上,子树内肯定存在一个叶子与一条不超过根所在子树的路径相连,那么其他点如果不能一步到达根,则一定不能通过两条路径直接到达,则构造合法。

于是我们通过求 LCA 即可快速求出 \(\text{faz}\),复杂度是 \(O(n\log n)\) 的。

CF1817E. Half-sum

考虑我们肯定是排序后选择一些前缀合成最小值,后缀合成最大值。并且通过手玩可以发现从后往前合并最小值,从前往后合并最大值,于是我们有一个 \(O(n^2)\) 的做法:对于每一个分界点我们维护一个高精度二进制数,对于每个二进制数求出来后暴力判断大小即可。考虑优化,我们先写出分界点为 \(p\) 时的贡献总和:

\[f(p)=\sum_{i=p+1}^{n}\dfrac{a_i}{2^{n+1-i}}+\frac{a_{p+1}}{2^{n-p}}-\sum_{i=1}^{p}\frac{a_i}{2^i}-\frac{a_p}{2^p} \]

对这个东西进行差分,考虑分界线从 \(p\) 变成 \(p+1\) 的贡献变化,有

\[\Delta_p=f(p+1)-f(p)=\dfrac{\delta_{p+1}}{2^{n-p-1}}-\dfrac{\delta_p}{2^p},\delta_p=a_{p+1}-a_p \]

接着对这个东西拓展一下,考虑将分界线从 \(p\) 移到 \(q\) 的贡献(\(p<q\)),于是我们有

\[\Delta_{p\to q}=\sum_{i=p}^{q-1}\Delta_i=-\frac{\delta_p}{2^p}+\frac{\delta_q}{2^{n-q}}+\sum_{i=p+1}^{q-1}\delta_{i}(\dfrac{1}{2^{n-i}}-\frac{1}{2^i}) \]

假设 \(p<q\le\dfrac{n}{2}\),那么和式的内容一定是负的,考虑此时只需要 \(\dfrac{\delta_p}{2^p}\ge\dfrac{\delta_q}{2^{n-q}}\) 就能保证 \(p\)\(q\) 优。首先我们排除 \(\delta_p=0\) 的情况。考虑到 \(q\le\dfrac{n}{2}\),于是 \(n-q\ge\dfrac{n}{2}\),又因为 \(\delta\) 的值域上限为 \(10^9\),所以只需要 \(p\le \dfrac{n}{2}-30\) 就可以保证 \(p\)\(q\) 优。也就是说如果在 \([1,\dfrac{n}{2}-30]\) 中存在 \(\delta_p\ne 0\),则这个位置肯定最优。否则我们无法判断 \((\dfrac{n}{2}-30,\dfrac{n}{2}]\) 中最优的那一个,但因为此时区间长度并不大,直接暴力即可。对于 \(\dfrac{n}{2}<p<q\) 同理,于是最多查询 \(O(\log V)\) 个区间,则复杂度为 \(O(n\log V)\)

CF1292E. Rin and The Unknown Flower

首先我们显然可以花费 \(2\) 的代价知道所有位置上的字母具体是什么,考虑沿用相同的思路,只是将字符串的长度略微调大。

更具体的,我们通过询问 CCCHCO 可以知道所有 C 的位置(最后一位除外),接着可以考虑询问 HOOO,这样可以知道所有 O 的位置(第一位除外)。那么也就是说此时在 \([2,n-1]\) 上未确定的位置一定是 H,于是我们最多不确定的位置就只有第一位和最后一位。如果第一位不确定,那么只可能是 HO,而最后一位只可能是 CH,于是我们最多有 \(4\) 种情况,询问 \(3\) 次后即可确定答案。则此时的总花费为 \(\dfrac{5}{2^2}+\dfrac{3}{n^2}\),很可惜只能通过 \(n>4\) 的情况。

考虑对于 \(n=4\) 的情况单独讨论,同样先询问 ccCHCOHO,如果这里面有的内容出现过,很显然最多只有两个位置不确定,并且除了最后一位,其他位置只可能是 HO 中的一个,而最后一个位置可能是 CHO 中的一个,因此最多有 \(6\) 种情况,询问 \(5\) 次后即可确定答案,则此时的总花费为 \(\dfrac{4}{2^2}+\dfrac{5}{n^2}\),可以通过。否则询问 OO,若出现过,则一定是出现了一个前缀的 O,否则一定存在一个 O 前面的位置无法填写,考虑如果第三位不确定,则其一定是 H,而最后一位是 CH,于是我们最多有 \(2\) 种情况,询问 \(1\) 次即可,总花费为 \(\dfrac{5}{2^2}+\dfrac{1}{n^2}\)。最后如果上述询问均为出现,那么中间两位一定是 HH,考虑查询 HHH。这样如果第一位仍旧不确定则为 O,否则为 H,最后一个不确定则为 C,否则为 H。于是我们一定可以确定整个串,代价为 \(\dfrac{5}{2^2}+\dfrac{1}{3^2}\)。可以通过。

LG4006. 小 Y 和二叉树

字典序最小是典型的贪心。考虑中序遍历的第一个点没有左儿子,则其度数至多为 \(2\),因此找到最小的 \(i\) 满足 \(k_i\le 2\) 即为第一个点。

接下来基于这个点开始拓展,这个点的其他相连结点 \(v\) 可以作为其右儿子或父亲。若 \(v\) 为右儿子,则中序遍历的下一个点类似第一个点,是 \(v\) 子树内编号最小的 \(i\) 满足 \(k_i\le 2\);若为父亲,则中序遍历的下一个点就是 \(v\)。对当前点的连边情况分讨:

  1. 如果当前点没有其他相连结点,那么显然无法继续拓展。
  2. 如果当前点恰有一个其他相连结点,那么这个点可以作为父亲,也可以作为右儿子,选择两种情况中贡献较小的情况。注意当两种贡献相同时,需要选择让这个点作为父亲,可以证明这样一定不劣。
  3. 如果当前点恰有两个其他相连结点,那么考虑这两个点谁作为右儿子,选择两种情况中贡献较小的情况。

当一个点被钦定为父亲时,其左儿子已经确定,剩下需要确定的依然是右儿子和父亲,可以递归求解。当一个点被钦定为右儿子时,我们需要决策其的左右儿子,类似地,我们依然对当前点的连边情况分讨。

考虑如何快速确定某个子树的贡献。不难想到,当确定第一个点后,接下来需要知道的所有子树的信息,都是以第一个点为根的子树的信息。因此使用 dfs 求解即可。上面的过程可以做到 \(O(n)\)

AGC028E. High Elements

看到字典序最小可以考虑按位贪心:先钦定第 \(i\) 位为 \(0\),判断此时是否有解,有解则确定为 \(0\),否则确定为 \(1\)

考虑如何判断当前状态是否存在可行解。假设当前两个序列 \(A,B\) 分别有 \(c_A\)\(c_B\) 个前缀最大值,最后一个前缀最大值分别为 \(v_A\)\(v_B\),在加入第 \(i\) 位以后的数后,新增的前缀最大值记为 \((a_i)\)\((b_i)\)。此时可以证明 \(a,b\) 中至少有一个序列不存在全局前缀最大值以外的值。

证明:

\(a,b\) 均存在非全局前缀最大值的值,那么交换这两个值所属的序列。因为这两个值并非原来全局前缀最大值,却在新的序列中是前缀最大值,说明原来偏序其的全局前缀最大值在另一个序列里。交换之后这两个前缀最大值均不造成贡献,若原来的 \(a,b\) 合法,则新的 \(a,b\) 也一定合法。

假设 \(a\) 的所有取值均为全局前缀最大值,那么设第 \(i\) 位以后存在 \(C\) 个全局前缀最大值,\(b\) 中存在 \(c\) 个全局前缀最大值和 \(c'\) 个非全局前缀最大值,那么此时两个序列的前缀最大值个数应该相等,即

\[c_A+C-c=c_B+c+c'\Rightarrow c_A+C-c_B=2c+c' \]

注意到此时等式的左边是定值,于是只需要让 \(2c+c'\) 的取值恰好为这个定值即可。考虑到 \(2c+c'\) 相当于将所有全局前缀最大值的权值设为 \(2\),其他值设为 \(1\) 之后的某个上升子序列的权值和。当一个序列的权值和为 \(x\) 时(\(x>1\)),可以删除一个 \(2\) 或两个 \(1\) 来使权值变为 \(x-2\)。那么可以只关心和那个定值奇偶性相同的权值的最大值即可,这样只需要维护一个最大权上升子序列。

\(f(i,0/1)\) 表示从 \(i\) 开始的权值和为偶数/奇数的上升子序列的最大权值和,用线段树辅助 dp 转移即可做到 \(O(n\log n)\) 预处理。在判断时,考虑取值全是全局前缀最大值的序列是 \(a\) 还是 \(b\),单次可以做到 \(O(\log n)\)。由于默认有解,因此最后构造出的解不满足 \(c_A=c_B\) 的话,就说明无解。总复杂度是 \(O(n\log n)\) 的。

CF533A. Berland Miners

先考虑如何判断当前是否存在一组解。一个洞穴的可进入高度是其根链上的最小值,每一个矿工都可以进入可进入高度不低于他的洞穴。通过贪心,从高到低枚举每一个矿工,使其进入其能进入的可进入高度最高的洞穴。不难看出这样做一定不劣,无解当且仅当可进入高度不低于第 \(i\) 高的矿工的洞穴数量 \(<i\)

不难考虑枚举改变高度的洞穴。在改变一个洞穴的高度后,一个洞穴的可进入高度会改变当且仅当改变了其根链上的严格最小值。因此,一个洞穴最多被一个洞穴影响,那么枚举产生的总影响量就是 \(O(n)\) 的。可以考虑二分将这个洞穴的高度修改成多少,设将高度修改为 \(H\),一个洞穴的可进入高度最终会变为 \(H\) 和其根链上的次小值取 \(\min\)。当一个洞穴的可进入高度从 \(h\) 变为 \(H\) 时,对答案的贡献相当于让身高在 \((h,H]\) 区间的矿工的可选洞穴数量 \(+1\)。用线段树维护每个矿工的可选洞穴数量,判断是否无解即可,复杂度可以做到 \(O(n\log^2n)\)

这样需要卡常。考虑如果初始状态第一个不合法的矿工的身高为 \(H\),那么无论修改哪个洞穴,都应该将高度修改为 \(H\)

证明:

如果修改高度 \(<H\),根据上面的过程,我们显然没有对这个不合法矿工造成任何影响,结果依然不合法。

如果修改高度为 \(H\) 不可行,那么一定存在某个身高 \(<H\) 的矿工不合法,此时继续调高修改高度也不会对这个矿工产生新的影响,也依然不合法。

于是我们可以省掉 \(O(\log n)\) 二分高度的复杂度,最终时间复杂度为 \(O(n\log n)\)

LG6936. [ICPC 2017 WF] Scenery

首先有一个 naive 的贪心:对于当前时间 \(s\),如果存在 \(s\in[a,b-t]\),取所有满足条件的区间中 \(b\) 最小的那个。但这样显然是有问题的,假设存在区间 \([a_1,b_1][a_2,b_2]\) 满足 \(a_1<a_2<b_2<b_1\),贪心在 \(a_1\) 开始拍照,则第二张照片只能在 \(a_1+t\) 开始拍,若 \(a_1+2t>b_2\) 则无法完成任务。但存在一种方案使得两张照片分别在 \(a_2+t\)\(a_2\) 时刻开始拍,是有可能完成任务的。

考虑推广这个内容。对于一个区间 \([s,e]\),取出所有拍摄时间被其包含的区间,并忽略其真实拍摄时间,认定其可以在 \([s,e]\) 之间任意拍摄,此时定然存在一个 \(C\) 满足无论如何安排方案,第一张照片的开始拍摄时刻都不会晚于 \(C\)。如果 \(C<s\),则不可能在 \(C\) 前拍摄 \([s,e]\) 中的照片,此时无解。否则考虑 \((C-t,s)\) 这个区间,如果在这个区间内开始拍摄了某一张照片,则 \([s,e]\) 中的照片也不可能在 \(C\) 前被拍摄,同样无解。因此 \((C-t,s)\) 这个区间不可以拍摄照片,叫做禁拍区间。

对于 \(s,e\) 只对给定的 \(a,b\) 有意义,因此禁拍区间最多只有 \(O(n^2)\) 个,然而考虑对于每个 \(s\),禁拍区间的右端点都相同,可以简单合并使禁拍区间变为 \(O(n)\) 个。在求解出所有的禁拍区间后,重新使用上面的贪心算法,此时构造出的解一定合法。

问题在于快速计算禁拍区间,考虑对所有照片按照左右端点升序排序,那么当从左边新加入一个照片时,区间的 \(C\) 至少会减小 \(t\),然而此时的 \(C\) 可能在某个禁拍区间内,由于 \(C\) 一直在减小,而禁拍区间的右端点也在减小,所以可以使用双指针快速更新不在禁拍区间内的最大的 \(C\),复杂度可以做到 \(O(n^2)\)

GYM104651I. Monster Generator

\(A_i=a_i+\Delta a_it,B_i=b_i+\Delta b_it\),当所有的 \(A_i,B_i\) 都确定的时候,可以给出一个贪心。将怪兽分为两类:

  1. \(A_i<B_i\),这样的怪兽打完会赚取血量。
  2. \(A_i\ge B_i\),这样的怪兽打完会亏损血量。

显然应该先打 \(1\) 类怪兽,再打 \(2\) 类怪兽。对于 \(1\) 类怪兽,按照 \(A\) 从小到大的顺序最优。对于 \(2\) 类怪兽,相当于 \(1\) 类怪兽的反过程,按照 \(B\) 从大到小的顺序最优。显然安排出的顺序 \(p\) 只有几种情况可能产生变化:

  1. 某个怪兽的 \(A\)\(B\) 变得相等。
  2. 某两个怪兽的 \(A\)\(B\) 变得相等。

怪兽的顺序 \(p\) 最多变化 \(O(n^2)\) 次。当确定了怪兽的顺序 \(p\) 后,所需的最大血量就是

\[\max(0,\sum_{1\le i\le t}A_{p_i}-\sum_{1\le i <t}B_{p_i})(1\le t\le n) \]

可以看作 \(n+1\) 条形如 \(kx+b\) 的直线取 \(\max\),使用凸包维护即可。对于每一条线段都有一段取到 \(\max\) 的时段,将这个时段和取到当前顺序的时段求交后计算这一段的贡献即可。复杂度可以做到 \(O(n^3\log n)\)

LG9600. [IOI 2023] 封锁时刻

\(\text{dis}(x,y)\) 表示 \(x,y\) 在树上的距离,那么 \(c_i\) 最多只有 \(O(1)\) 种取值:\(0\)\(\text{dis}(X,i)\)\(\text{dis}(Y,i)\)。现在有两种情况:存在或不存在点能同时从两个起点到达。

对于不存在点能同时从两个起点到达的情况,可以对两个点同时贪心,每个点可以花费 \(\text{dis}(X,i)\) 的代价可以使答案 \(+1\),也可以花费 \(\text{dis}(Y,i)\) 的代价使答案 \(+1\)。只需要对所有的 \(\text{dis}\) 排序后从小到大贪心即可。因为每个点的 \(\text{dis}\) 比它的父亲大,所以在选择其之前一定会选择其父亲,也就是说能从 \(X,Y\) 到达的点一定连通。如果贪心存在某个点同时能从两个点到达,因为此时的花费比真实的花费大,肯定不如在另一种情况时优。

对于存在点能同时从两个起点到达的情况,可以看出 \(X,Y\) 路径上的点一定至少可以到达其中的某一个点,先钦定这些点已经花费 \(\text{dis}\) 的较小值获得了 \(1\) 的贡献,还可以继续花费两个 \(\text{dis}\) 的差额外获得 \(1\) 的贡献。对于其他点来说,可以花费 \(\text{dis}\) 的较小值获得 \(1\) 的贡献,也可以花费 \(\text{dis}\) 的较大值获得 \(2\) 的贡献。这个是经典的贪心,下面给出一个解法。

记使贡献为 \(1\) 的花费为 \(A\),使贡献为 \(2\) 的花费为 \(B\)。考虑每次新增一个贡献有 \(4\) 种情况:

  1. 将一个贡献为 \(0\) 的点变为贡献为 \(1\) 的点,花费为 \(A_i\)
  2. 将一个贡献为 \(1\) 的点变为贡献为 \(2\) 的点,花费为 \(B_i-A_i\)
  3. 将一个贡献为 \(1\) 的点变为贡献为 \(0\) 的点,另挑一个贡献为 \(0\) 的点变为贡献为 \(2\) 的点,花费为 \(B_j-A_i\)
  4. 将一个贡献为 \(2\) 的点变为贡献为 \(1\) 的点,另挑一个贡献为 \(0\) 的点变为贡献为 \(2\) 的点,花费为 \(B_j+A_i-B_i\)

维护 \(A_i,B_i-A_i,B_i,-A_i,A_i-B_i\) 的五个小根堆即可,复杂度为 \(O(n\log n)\)

和之前情况的贪心类似的,由于同样的贡献,自己父亲的花费定然比自己的要小,那么贪心给出的贡献为 \(2\) 的点必然连通,贡献为 \(1,2\) 的点也必然连通,因此贪心给出的解一定合法。

对上面两种情况的答案取 \(\max\) 即可,复杂度是 \(O(n\log n)\) 的。

LG11051. [IOI 2024] 树上代价

考虑 \(w_i=1\) 时的贪心策略。先给叶子节点赋权,目前节点的子树和为所有叶子节点的权值和,由于最终要求子树和在 \([L,R]\) 内,因此至少需要 \(\max(0,\sum c-R)\) 次调整。设 \(u\) 子树内叶子的个数为 \(k_u\),当所有叶子的权值都为 \(L\) 时有最小值 \(\max(0,k_uL-R)\)。对于每个点的 \(k\) 是其儿子 \(k\) 的和,显然有 \(\max(0,k_uL-R)\ge\sum\max(0,k_vL-R)\),因此当前子树所需的操作一定足够可以下放到儿子上,因此最终的操作次数即根节点的所需操作次数,还需要加上所有叶子节点的初始代价。

进一步考虑 \(w_i\le 1\) 时的贪心策略。考虑 \(w_i=0\) 的点无论如何调整都没有代价,因此不如在其上将子树和调整为 \(L\),也就是可以将其视为叶子节点。此时通过断开所有 \(w_i=0\) 的点和儿子的连边,整张图会变为一个森林,代价即为所有树的代价和。假设森林中叶子节点个数为 \(k\) 的树的个数为 \(f(k)\),操作总次数即为 \(\sum f(k)\cdot\max(0,kL-R)\),这个内容直接枚举可以做到 \(O(QN)\)。由于 \(f\) 在给出图后便确定,可以考虑预处理出所有 \(f\),结合 \(\max(0,kL-R)\) 的单调性,找到最小的 \(k\) 满足 \(kL-R\ge 0\)\(\lceil\frac{R}{L}\rceil\),答案即为 \(L\sum kf(k)-R\sum f(k)\),维护 \(kf(k),f(k)\) 的后缀和即可 \(O(1)\) 查询。同理仍需加入所有叶子节点的初始代价。

进一步拓展到 \(w_i\) 任意的情况。考虑最优策略肯定是在 \(w_i\) 更小的位置上放更多的操作次数。因此只需要对于所有 \(x\),将 \(w_i\le x\) 的点的 \(w_i\) 视为 \(0\)\(w_i> x\) 的点的 \(w_i\) 视为 \(1\),就可以得到此时将所有 \(w_i\le x\) 的点的操作次数拉满时的最小总操作次数,对所有 \(x\) 的情况求和就是答案。考虑类扫描线思路,从大到小枚举 \(w\),向图中加入点,用并查集维护所有连通块的叶子节点个数,累加到 \(f\) 上,这样可以做到 \(O(NW)\)。考虑当加入 \(w\)\(i\) 大的点时,每一个连通块都有 \(w_i-w_{i+1}\) 的贡献,可以考虑差分。当一个连通块产生的时候有 \(w_i\) 的贡献,消失的时候有 \(-w_i\) 的贡献,在对应位置上加和即可,同样可以用并查集维护,复杂度是 \(O(n\alpha(n))\) 的。

LG6631. [ZJOI2020] 序列

假设总共有 \(k\) 种本质不同的操作,考虑给每种本质不同的操作一个操作次数 \(x_i\) 和操作位置的集合 \(s_i\)。那么根据线性规划,题目要求的是

\[\begin{aligned} &\min &\sum_{1\le i\le k} x_i,\\ &s.t.&\forall i,\sum_{i\in s_j}x_j\ge a_i\\ &&\forall i,\sum_{i\in s_j}-x_j\ge -a_i\\ &&\forall j,x_j>0 \end{aligned} \]

由于目标函数的各项系数是常数,可以想到求解这个线性规划的对偶问题

\[\begin{aligned} &\max &\sum_{1\le i\le n} a_i(y_i-z_i),\\ &s.t.&\forall j,\sum_{i\in s_j}(y_i-z_i)\le 1\\ &&\forall i,{y_i,z_i>0} \end{aligned} \]

由于 \(y_i,z_i\) 始终同时出现,考虑令 \(w_i=y_i-z_i\)。现在只考虑整数情况。问题相当于对每个位置赋一个权值 \(w\),使得所有本质不同操作对应的位置上的权值和 \(\le 1\)。相当于原序列、奇序列、偶序列的最大子段和均 \(\le 1\)。考虑最大子段和的 dp 转移:\(f_i=\max(0,f_{i-1})+a_i\),因此只需要在 dp 状态中维护 \(\max(0,f_{i-1})\) 即可。

更具体的,设 \(f(i,x,y,z)\) 表示前 \(i\) 位中整个序列、奇序列、偶序列的最大后缀和为 \(x,y,z\) 时最大的 \(\sum a_iw_i\)。由于原序列、奇序列、偶序列的后缀都是一个操作,因此 \(x,y,z\in\{0,1\}\),转移的时候枚举每一位的 \(w\) 更新最大后缀和即可。看似 \(w\) 的取值很广,但由于要转移到 \(\max(0,x+w)\),有 \(w\le 1\)。同时 \(x+w<0\) 时显然 \(w<-1\),不如将 \(w\) 调整为 \(-1\)。综上 \(w\in\{-1,0,1\}\),转移可以做到 \(O(n)\)

LG8341. [AHOI2022] 回忆

对每一个路径都给一个目标深度,表示其完成分配给它的点对至少需要达到的深度。两条不交的达到目标深度的路径可以匹配起来,从而每个点都有尚未达成目标的路径数、达成目标但未匹配的路径数、达成目标的路径匹配对数。

对于达成目标但未匹配的路径数肯定能匹配就匹配,因为匹配的路径对可以拆开,但未匹配的路径后面就不一定能合起来了。

对于未达成目标的路径只保留目标深度更小的那个路径,剩下的路径在到达目标深度后就可以当作未匹配的路径了,只需要在目标点打一个标记即可。

合并两个子树的信息可以贪心合并,记有较多未匹配路径的的子树为 \(X\),较少的为 \(Y\)。若 \(Y\) 拆开所有匹配的路径对后,未匹配的路径数仍小于 \(X\),那么只能将这些路径和 \(X\) 中的匹配才能使 \(X\) 剩余的未匹配路径最少。否则可以拆开一些匹配对后和 \(X\) 中的路径匹配,\(X\) 中最多多出一条未匹配路径。

考虑在某个点 \(u\) 处加入某个点对 \((v,u)\),此时如果 \(u\) 有保留的未达成目标的路径,和 \(v\) 的深度取较小值即可。否则,如果存在已完成目标的未匹配路径,将这个路径变成为完成目标的路径,如果不存在,如果有匹配的路径对,先拆开一对路径,然后进行相同操作。

只需要遍历一遍树即可贪心递推出上面的结果,复杂度是 \(O(n)\) 的。

posted @ 2025-06-12 08:20  DycIsMyName  阅读(37)  评论(0)    收藏  举报