wtcl/kk

本博客将会收录一些贪心/构造的我认为较有价值的题目,这样可以有效的避免日后碰到 P7115 或者 P7915 这样的题就束手无策进而垫底的情况/dk

某些题目虽然跟贪心关系不大,但是在 CF 上有个 greedy 的 tag,这种题目大概率也会被我收录进来(比方说这篇博客里大概率会收录不少 DP 题,因为 CF 上不少 DP 题都莫名其妙地打上了一个 greedy 的 tag

1. CF1592F1 Alice and Recoloring 1

首先很明显我们不会选择翻转包含 \((1,m),(n,1)\) 的矩形,因为它们完全可以等效于翻转两次包含 \((1,1)\) 的矩形,而前者代价不小于 \(2\),后者代价为 \(2\),因此我们只用考虑包含 \((n,m)\) 的矩形即可。

我们考虑记 \(a_{x,y}\) 表示 \((x,y)\) 格子颜色是否为黑色,再记 \(b_{x,y}=a_{x,y}\oplus a_{x,y+1}\oplus a_{x+1,y}\oplus a_{x+1,y+1}\),那么可以发现 \(1\) 操作等价于单点翻转 \((x,y)\)\(b\) 值,而 \(4\) 操作等价于翻转 \((x-1,y-1),(x-1,m),(n,y-1),(n,m)\) 四个点的 \(b\) 值,注意到一个性质就是我们 \(4\) 操作使用的次数肯定不会超过 \(1\),因为两次操作 \(4\) 可以用六次操作 \(1\) 代替,而二者代价都是 \(6\),因此我们完全可以将两次 \(4\) 操作变为 \(6\)\(1\) 操作且答案不会变得更劣。

这样问题就简单了,我们统计一下有多少个 \(b_{x,y}=1\),再统计一下是否存在一组 \((x,y)\),满足 \(b_{x-1,y-1},b_{x-1,m},b_{n,y-1},b_{n,m}\) 均为 \(1\),如果存在则可以将这四次 \(1\) 操作变为一次 \(4\) 操作,答案减少 \(1\)

时间复杂度 \(\mathcal O(nm)\)

2. CF1592F1 Alice and Recoloring 2

和上一题一样,我们同样不会翻转包含 \((1,m),(n,1)\) 的矩形,结论同上。

与上一题不同的是,由于此题翻转 \((n,m)\) 的代价为 \(2\)​,因此“翻转包含 \((n,m)\) 的矩形的次数不超过 \(1\)“这一结论就不再成立了,我们不妨来挖掘一下其他性质。我们记集合 \(S\) 表示 \(4\) 操作作用过的点,那么可以发现以下性质:

Observation 1. \(\forall (x,y),(x’,y’)\in S\),都有 \(x\ne x’,y\ne y’\)

因为如果我们翻转两个在同一行的元素,我们完全可以用 \(4\)\(1\) 操作代替两次 \(2\) 操作。而二者拥有相同的花费。

Observation 2. \(\forall (x,y)\in S\),都有 \(b_{x-1,y-1}=b_{x-1,m}=b_{n,y-1}=1\)

否则翻转完这个含 \((x,y)\) 的矩形后,肯定会有至少一个 \(0\) 变成了 \(1\),此时我们肯定要再花至少 \(1\) 的代价把这个 \(1\) 变回 \(0\),而这样一来就已经有 \(3\) 的代价了,肯定不比直接翻 \(3\) 个点更优。

这样一来模型就很明显了,我们希望尽可能多地使用 \(4\) 操作,而使用 \(4\) 操作需要满足 \(b_{x-1,y-1}=b_{x-1,m}=b_{n,y-1}=1\)\(x-1,y-1\) 互不重复,这样能比不用 \(4\) 操作节省 \(1\) 的代价,这不禁令我们往二分图匹配的方向去思考。具体来说我们建立两排点,如果 \((x,y)\) 满足 \(b_{x-1,y-1}=b_{x-1,m}=b_{n,y-1}=1\),那么我们就从左部的 \(x\) 点向右部的 \(y\) 点连一条边,然后跑二分图最大匹配即可知道我们最多可以使用多少次 \(4\) 操作,这样通过网格上 \(1\) 的个数,减去二分图最大匹配的大小即可得到答案。注意到每次使用 \(4\) 操作都会改变一次 \(b_{n,m}\),因此如果二分图最大匹配是奇数,我们在统计网格上 \(1\) 的个数时,要反转 \(1\) 的状态。

3. CF1521D Nastia Plays with a Tree

彻底废柴了/dk,连 2500 的贪心题都做不出来了

首先我们想到一个非常假的贪心:我们从上至下对树进行一遍 DFS,然后每次尝试将每个点的子树变成一条链,如果发现儿子个数 \(\ge 2\) 就将那些分叉摘下来贴到一个儿子处。

该做法一脸过不去的样子,离谱到连样例都过不去,其原因在于它忽略了一种情况:那就是如果一个点的子树有两个分叉,并且两个分叉都是一条垂下去的链,那么如果抛开这个点与其父亲的边,那么这个点的子树也是一条链,因此合并时需要分情况讨论。我们将“去掉一个点与其父亲的连边后,子树是一条链”的子树,分为“一条垂下去链”和“由两条垂下去的链组合而成的链”两种情况讨论:

  • 如果这个点的子树中,有至少两条“一条垂下去链”,那么我们会选择保留这两条垂下去的链,合并成一条“由两条垂下去的链组合而成的链”,然后其他链都接到这条链上。
  • 如果这个点的子树中,恰有一条“一条垂下去链”,那么我们直接将其他链都接到这条链上形成一条更大的“一条垂下去链”即可。
  • 如果这个点的子树中,没有“一条垂下去链”,那么我们随便选择一条“由两条垂下去的链组合而成的链”,然后将其余链都接到这条链上即可。

时间复杂度 \(\mathcal O(n)\)

4. CF1455F String and Operations

考虑 DP。注意到进行完前 \(i\) 次操作之后,\(s_{i+1}\) 要么在 \(i\),要么在 \(i+1\),取决于上一次 \(s_i\) 是否在 \(i\) 位置且上一次执行的是否是 R 操作。因此设 \(dp_{i,0/1}\) 表示进行完前 \(i\) 次操作后,\(s_{i+1}\) 否/是被移到了 \(i\) 位置后最小的字典序,转移就分 OUDLR 五种情况转移即可,时间复杂度 \(\Theta(n^2)\)

针对上述平方的 dp 我们其实还有进一步优化的空间。注意到每次操作我们只会影响 \([i-2,i+1]\) 这段区间内位置上的值,因此我们字符串只用存 \(4\) 位,每次 DP 过程中确定出 \(s_{i-3}\) 的最小值,然后从 \(s_{i-3}\) 达到最小值的位置转移即可。这样复杂度可优化到线性。

提交记录