20251021

2025 正睿二十连测

B

给定一个长度为 \(n\) 的序列 \(a\),求它最长的子序列 \(b\) 使得 \(b\) 里没有距离 \(\le 2\) 的相同值(\(b_i \ne b_{i - 1}, b_i \ne b_{i - 2}\))。输出长度即可。

有个简单粗暴的 DP,令 \(dp_{i, j}\) 表示以 \(i\) 结尾的子序列,倒数第二个元素值为 \(j\) 的最长子序列长度。暴力转移是 \(O(n^3)\) 的。

考虑优化。先尝试优化状态:因为只要求 \(b_i \ne b_{i - 2}\),所有对于每个 \(i\) 只需要记录 \(dp_{i, j}\) 的最大值、次大值以及最大值对应的 \(j\),时间复杂度降为 \(O(n^2)\)

再考虑优化转移,不难发现 \((b_i, b_{i + 1})\) 里只有最多 \(4\) 种不同的颜色,再多就可以再插入一个。所以转移只需要从前面的 \(5\) 种颜色转移,时间复杂度:\(O(n)\)

这个题主要就是优化 DP,状态优化较简单,转移稍微难想一点。

C

给定 \(n(n \le 5000)\) 个数 \(a_1 \sim a_n\) 以及 \(d\)。要将每个数染为黑白两色之一。满足 \(a_x + a_y \ge d\)\(a_x, a_y\) 同色的有序数对 \((x, y)\) 尽可能少。 输出最少的数对以及划分的方案数。

一个小 trick 题。我们将满足条件的 \(x, y\) 之间连边。

\(a_x\) 分为 \(< d / 2\) 的与 \(\ge d / 2\) 的(后面成 \(< d / 2\) 的为小数,\(\ge d / 2\) 的为大数)。这有什么好处呢?就是小数之间一定没有连边,大数之间一定有连边,只有小数和大数之间的关系是确定的。

因为如果直接暴力做的话,要记录之前所有数的颜色状态,就起飞了。所以我们要找到一个合理的排序方式,使得只考虑一个数向前的连边,枚举这个点的颜色后知道同色的边数。换句话说,就是可以通过很少的信息快速的得到前面有多少个点与他同色且有连边。

考虑按 \(d, 0, d - 1, 1 \dots\) 这种方式。这种方式的好处是每个小点和前面的大点均有连边,每个大点和前面的小点都没有连边。这样对于每个点,一定满足前面的大点和小点可以捆在一起算,因为与他的连边关系是一样的。

那么就可以进行 DP 了,令 \(dp_{i, j}\) 表示前 \(i\) 个数中有 \(j\) 个大点是黑色的,暴力转移即可。

时间复杂度:\(O(n^2)\)

这题主要是想到将 \(a_x\) 化成大点和小点,这样经过排序后只需要记录大点的数量就可以知道有多少个点与当前点连边了。

posted @ 2025-10-21 22:14  xiehanrui0817  阅读(5)  评论(0)    收藏  举报