2025.10.20~2025.10.26
2022HDU多校08
A
Problem
\(T\) 组数据。给定一个字符串 \(|s|\),每次可以选择一段长度为奇数的子串进行翻转,求能得到的字典序最小的字符串。
\(1 \le T \le 10\),\(|s| \le 10^{5}\)。
Solution
由于只能选择奇数长度的段进行反转,因此奇偶性不同的两个位置永远不能实现交换。
而取长度为 \(3\) 的段总能使相邻两个奇偶性相同的位置进行交换,因此只需对奇子列和偶子列分别排序即可。
B
Problem
\(T\) 组数据。给定一个长为 \(n\) 的数列 \(a\),保证 \(a\) 中的元素不重复。称 \(a\) 的一个连续子序列 \(b = [b_{1}, b_{2}, \dots, b_{m}]\) 是 ridiculous 的,当且仅当 \(b\) 中的最大值位于 \(b\) 中的奇数下标,最小值位于 \(b\) 中的偶数下标。求将 \(a\) 划分为若干 ridiculous 连续子序列的方案数。答案对 \(998244353\) 取模。
\(1 \le T \le 5\),\(1 \le n \le 3 \times 10^{5}\),\(1 \le a_{i} \le 10^{9}\),\(a_{i}\) 互不相同,\(\sum{n} \le 10^{6}\)。
Solution
记 \(f_{i}\) 表示考虑前 \(i\) 个位置的划分方案数。则 \(f_{i} = \sum\limits_{1 \le j \le i \and [j, i] \text{ is ridiculous}}f_{j - 1}\)。
问题就是如何快速找到那些满足条件的 \(j\)。
为了解决 “最大值在哪” 这个问题,维护一个值递减的单调栈(存位置),记单调栈内相邻两个元素为 \(x, y(x < y)\),则 \(\forall j \in (x, y]\),\(\max\limits_{j \le k \le i}a_{k} = a_{y}\)。
为了解决 “最大值位置为奇数” 这个问题,对奇数位置和偶数位置分别维护(开两棵线段树)。\(\forall j \in (x, y]\),若 \(j\) 与 \(y\) 奇偶性相同,则 \([j, i]\) 能够满足最大值的条件。
最小值同理。
由于只有同时满足最大最小值的 \(j\) 才能将 \(f_{j - 1}\) 转移给 \(f_{i}\),因此不妨维护 \(cnt\) 表示区间内某个位置满足条件个数的最大值,\(sum\) 表示 \(cnt\) 最大的所有位置的 \(f\) 值之和。对于当前 \(f_{i}\),若一棵线段树全局 \(cnt\) 值为 \(2\),则 \(f_{i}\) 加上这棵线段树的全局 \(sum\) 值。更新单调栈时同时维护相应线段树上的信息。
答案为 \(f_{n}\)。
C
Problem
\(T\) 组数据。给定一个 \(n \times m\) 的小写字母矩阵。称一条路径是合法的,当且仅当这条路径只能向下或向右走,且经过的字母构成一个回文串。求将该矩阵划分为若干合法路径的方案数。
\(1 \le T \le 10\),\(n, m \le 6\)。
Solution
神仙搜索,神仙状压。
对每个位置预处理出以它为起点的所有可行回文路径,路径以二进制形式存储。可以想到有效的路径数量并不多。
问题转化为:有若干二进制状态,求用这些状态不重不漏地拼出全集 \(2^{nm} - 1\) 的方案数。
直接进行记忆化搜索,每次选取二进制下最低位作为起点,枚举不与当前状态相交的路径进行递归。
经检验,\(6 \times 6\) 的全 a 矩阵有效状态数为 \(2 \times 10^{6}\) 出头。
时限 15s,放心跑。
D
Problem
\(T\) 组数据。平面直角坐标系上有 \((n + 1)^{2} - 1\) 个横纵坐标位于 \([0, n]\) 的整点(去除 \((0, 0)\))。
求最少用几条直线能在不穿过 \((0, 0)\) 的情况下穿过所有 \((n + 1)^{2} - 1\) 个整点。
\(1 \le T \le 50\),\(0 \le n \le 50\)。
Solution
签到题,直接猜答案为 \(2n\)。
证明:先证明答案下界为 \(2n\):若没有与坐标轴平行的直线,则一条直线最多穿过 \(2\) 个边界点,而边界上共有 \(4n\) 个点,因此至少需要 \(2n\) 条直线;否则,假设画了 \(k_{1}\) 条横线、\(k_{2}\) 条竖线,然后划归为一个子问题,同样能说明下界为 \(2n\)。
而 \(x + y = 1, 2, \dots, 2n\) 显然是一组直线数量为 \(2n\) 的合法解,因此答案就是 \(2n\)。
E
Problem
\(T\) 组数据。给定一条有 \(n\) 个点的链,第 \(i\) 个点的点权为 \(a_{i}\),\(i\) 与 \(i + 1\) 的边权为 \(b_{i}\),\(b_{i}\) 为质数。定义一次起点为 \(s\) 的 trip 如下:
- 有一个装质数的背包,初始时装入 \(a_{s}\) 的所有质数。
- 只能向相邻的点移动。如果背包中含有边权质数,则可以经过,并装入下一个点权的所有质数;否则不能经过。
- 可以反复经过点和边。
\(Q\) 组询问 \((x, y)\),判断以 \(x\) 为起点进行 trip 是否能到达 \(y\)。
\(1 \le T \le 3\),\(2 \le n, Q \le 2 \times 10^{5}\),\(1 \le a_{i}, b_{i} \le 2 \times 10^{5}\)。
Solution
只需预处理出每个位置能到达的范围即可 \(O(1)\) 查询,记第 \(i\) 个位置的最大可达范围为 \([L_{i}, R_{i}]\),初始化 \(L_{i} = R_{i} = i\)。
(注意 \([L_{i}, R_{i}]\) 是不断被更新的;两个位置是否可达也要考虑当前它们已经能到达的区域)
先规定只能向右走,从后往前枚举,求出每个位置向右能走到的最远位置。
具体地:
-
如果 \(i\) 能到达 \(i + 1\),则 \(R_{i} = R_{i + 1}\)。
-
这还没完,\(R_{i}\) 有可能比 \(R_{i + 1}\) 更大,因为 \(a_{i}\) 可能贡献出有助于扩展的质因子。所以让 \(R_{i}\) 继续向后跳,直到无法扩展为止。
分析一下:我们记不能跳的地方为 “断点”,有 \(O(n)\) 个断点。当一个断点能够被跳过去,它就不会再被遍历。
然后再从前往后枚举,求出每个位置的最大可达范围。
具体地:
-
如果 \(i\) 与 \(i - 1\) 互达,则直接令 \([L_{i}, R_{i}] = [L_{i - 1}, R_{i - 1}]\),因为该情况下 \(i\) 与 \(i - 1\) 能到达的范围一定相同。
-
如果 \(i\) 无法到达 \(i - 1\),则位置 \(i\) 无法往前走,则它能到达的范围只能是 \([i, R_{i}]\)。
-
如果 \(i\) 能到达 \(i - 1\) 但 \(i - 1\) 不能到达 \(i\)(即 \(R_{i - 1} = i - 1\)), 则从位置 \(i\) 向左右扩展,方法类似上述的只向后扩展的做法。
(还不会证这个情况时间复杂度QWQ)(别急,有反转)
判断是否可达:可以用 vector 存下每个质数的出现位置,在相应的 vector 上二分查询一段区间内是否出现过该质数。
upd:官方的做法是错的,s下面这组数据能够卡掉下发的 std(来源于知乎):
#include <iostream>
#include <cstdio>
using namespace std;
int main () {
//freopen("rand.txt", "w", stdout);
printf("1\n");
printf("200000 1\n");
for (int i = 1; i <= 200000; i ++) printf("%d ", (i & 1) ? (((i + 1) % 4 == 0 ? 5 : 2)) : 3);
printf("\n");
for (int i = 1; i < 200000; i ++) printf("%d ", (i & 1) ? 3 : ((i % 4 == 0 ? 5 : 2)));
printf("\n");
printf("1 200000\n");
return 0;
}
问题还是出在 \(i\) 能到达 \(i - 1\) 且 \(R_{i - 1} = i - 1\) 的情况,官方的 std 能被卡成 \(O(n^{2}\log{n})\)。
to be done.
G
Problem
\(T\) 组数据。给定正整数 \(n\) 和 \(n\) 元排列 \(p\)。现有一个 \(n\) 个点的完全图,点 \(i, j\) 的边权为 \(|i - j| \times |p_{i} - p_{j}|\)。求该图的最小生成树边权和。
\(1 \le T \le 5\),\(1 \le n \le 50000\)。
Solution
先构造出这样一棵生成树:\(i\) 与 \(i + 1\) 连边,这样每条边的边权 \(\le n - 1\)。
由 Kruskal 算法的原理知,最小生成树的边权一定 \(\le n - 1\),即有用的边一定满足 \(|i - j| \times |p_{i} - p_{j}| \le n - 1\)。
则一定有 \(|i - j| \le \sqrt{n - 1}\) 或 \(|p_{i} - p_{j}| \le \sqrt{n - 1}\)。
而 \(p\) 是 \((1, 2, \dots, n)\) 的一个排列,所以有用的边数是 \(O(n\sqrt{n})\)。
可以在 \(O(n\sqrt{n})\) 的时间复杂度找出这些边再做 Kruskal 算法,时间复杂度 \(O(n\sqrt{n}\alpha(n))\)。
不要用 sort,\(O(n\sqrt{n}\log{n})\) 是无法接受的(可以用自然排列卡掉)。由于边权很小,所以直接用桶排即可。
还有注意要开 long long。
H
Problem
\(T\) 组数据。给定一棵 \(n\) 个点的树,定义一个分离集如下:
- 是一个点集 \(S\),且满足:如果仅保留这些点之间的边,则每个点的度数至多为 \(1\)。
求该树的最大分离集大小。
\(1 \le T \le 10\),\(1 \le n \le 500000\)。
Solution
记 \(f_{u, 0 / 1/ 2}\) 分别表示仅考虑 \(x\) 子树,选择 \(x\) 且 \(x\) 度数为 \(0\)、选择 \(x\) 且 \(x\) 度数为 \(1\)、不选 \(x\) 的合法最大分离集大小。
然后做个简单的线性树形 DP 即可。
I
Problem
\(T\) 组数据。给定一棵 \(n\) 个点的有根树,以 \(1\) 为根。定义一次 access 操作如下:
- 操作 \((x, c, p)\):有 \(p\) 的概率,将 \(x \to 1\) 路径上的所有点权赋值为 \(c\),并将与该路径相邻的点权赋值为 \(0\)。
现在给定 \(m\) 个 access 操作 \((x_{i}, c_{i}, p_{i})\)。求按顺序进行 \(m\) 次 access 操作后,整棵树点权和的期望值。答案对 \(10^{9} + 7\) 取模。
\(1 \le T \le 4\),\(1 \le n, m \le 2 \times 10^{5}\)。
Solution
考虑 \(u \to fath_{u}\) 这一条边对答案的贡献。
如果在 \(fath_{u}\) 的子树内,操作 \((v, c, p)\)(其中 \(v\) 在 \(u\) 的子树内)是最后一个被执行的,则 \(u \to fath_{u}\) 的颜色为 \(c\)。
考虑以操作时间作为下标建立线段树,对区间 \([l, r]\) 维护 \(prod =\prod\limits_{l \le i \le r}(1 - p_{i})\) 与 \(sum = \sum\limits_{l \le i \le r}c_{i}p_{i}\max(1, \prod\limits_{i < j \le r}(1 - p_{j}))\),前者用于方便计算 \(sum\),后者即为我们希望得到的期望值。
对操作 \((x_{i}, c_{i}, p_{i})\) 初始化线段树 \(root_{x}\) 的第 \(i\) 个位置,然后做线段树合并。
合并到以 \(u\) 为根的子树时,统计 \(u\) 子树内除了在点 \(u\) 处之外的所有操作对 \(v \to u(v \in son_{u})\) 的贡献。
这些贡献加起来就是整棵树的期望边权和。
K
Problem
\(T\) 组数据。现有一个 \(n \times m\) 的矩阵,求最多能切多少刀,使每个小矩阵的面积不少于 \(k\)。
\(1 \le T \le 100\),\(1 \le n, m, k \le 10^{5}\)。
Solution
枚举某一维的边长即可。
L
Problem
\(T\) 组数据。给定非负整数 \(k\),要求构造一棵有根二叉树,使得每个点要么是叶子要么有两个儿子,且深度之和为 \(k\)。根节点深度为 \(0\)。定义深度序列 \((dep_{0}, dep_{1}, \dots dep_{m})\),其中 \(m\) 表示深度最大值,\(dep_{i}\) 表示深度为 \(i\) 的点数。求最小化点数的情况下最小的深度序列。若不存在输出 \(-1\)。
\(1 \le T \le 10\),\(0 \le k \le 10^{12}\)。
Solution
显然 \(k\) 为奇数时无解。
不妨转化为数列问题:构造一个有限数列 \(\{ a_{1}, a_{2}, \dots, a_{d} \}\),数列需要满足以下条件:
-
\(a_{1} \le 1\)
-
\(a_{i} \le 2a_{i - 1}\)
-
\(w = \sum\limits_{1 \le i \le d}ia_{i} = \frac{k}{2}\)
数列 \(a\) 对应树的节点数为 \(1 + 2\sum\limits_{1 \le i \le d}a_{i}\),数列 \(a\) 的字典序关系与深度序列的字典序关系一致。
为了最小化节点数,即最小化 \(s = \sum\limits_{1 \le i \le d}a_{i}\),一个显然的思路是令所有 \(a_{i}\) 尽量等于 \(1\),这样一来可以确定 \(d\) 的上界是 \(O(\sqrt{n})\) 级别的。
不妨设有一个全 \(1\) 数列,且其项数 \(d\) 满足 \(\sum\limits_{1 \le i \le d}i = \frac{d(d + 1)}{2} \le \frac{k}{2}\) 即 \(d(d + 1) \le k\)。
如果 \(d(d + 1) = k\):该结构就是合法的最优解,直接输出即可。
否则,数列 \(a\) 必须进行一定的改动。比如,\(s \ge d + 1\)。
如果仍然在 \(d\) 项全 \(1\) 数列的基础上思考,并考虑如何让 \(a_{i} = 1\) 变成 \(a_{i} = x\),那么问题会很棘手。
项数 \(d\) 不应该成为绊脚石,全 \(1\) 数列不应该成为绊脚石,毕竟它们不是答案的第一决定因素。
但这并不意味着先前的工作一无是处。比如,我们知道了 \(s \ge d + 1\)。
那就让 \(s\) 来主导思考的方向吧!
一个 \(s\) 值可以确定 \(w\) 的上下界:下界的情况就是把深度较浅的节点填满,上界的情况就是全 \(1\) 数列。为方便表示,记 \(V_{w}(s)\) 表示 \(s\) 所确定的 \(w\) 的取值集合。
我们可以肯定:\(K = \frac{k}{2}\) 小于 \(V_{w}(d + 1)\) 的上界。
那么下界如何呢?
- \(\inf{V_{w}(1)} = 1\),\(\sup{V_{w}(1)} = 1\)
- \(\inf{V_{w}(2)} = 3\),\(\sup{V_{w}(2)} = 3\)
- \(\inf{V_{w}(3)} = 5\),\(\sup{V_{w}(3)} = 6\)
- \(\inf{V_{w}(4)} = 8\),\(\sup{V_{w}(4)} = 10\)
- \(\inf{V_{w}(5)} = 11\),\(\sup{V_{w}(5)} = 15\)
- \(s \ge 5\) 时:总有 \(\sup{V_{w}(s)} \ge \inf{V_{w}(s + 1)} - 1\)
即:除 \(K = 2, 4, 7\) 即 \(k = 4, 8, 14\) 外,\(K = \frac{k}{2}\) 一定介于 \(V_{w}(d + 1)\) 的上下界之间。
事情的发展开始变得清晰;我们很清楚我们希望看到怎样的结论:\(V_{w}(s)\) 是一段连续的值域。
正确性显然!从下界的情况出发,每次选取最大的 \(a_{i} > 1\),令 \(a_{i + 1}\) 加一,\(a_{i}\) 减一。在到达上界之前,该操作总可以被执行,\(a\) 序列也总是合法,且 \(w\) 每次增加 \(1\)。
也就是说,\(s = d + 1\) 时一定有解!
于是我们证明了答案的存在性。
接下来,为了最小化序列字典序,我们希望深度较浅的节点数较少,即序列 \(a\) 中靠前的元素值较小。
假设我们已经确定了 \(a_{1} \sim a_{i - 1}\),令 \(s^{'} = s - \sum\limits_{1 \le j < i}a_{j}\),\(K^{'} = \frac{k}{2} - \sum\limits_{1 \le j < i}ja_{j}\)。
此时 \(s^{'}\) 当然也确定了 \(w^{'} = \sum\limits_{j \ge i}ja_{j}\) 的上下界,并且 \(w^{'}\) 值域连续,原理同上。我们假定在之前的构造过程中,保证进行到这一步时:\(s^{'}\) 可以确定出一段 \(w^{'}\) 的值域包含 \(K^{'}\)。初始条件即 \(s = d + 1, K = \frac{k}{2}\),显然满足。
但是,\(s^{'}\) 具体(即考虑了 \(a_{i}\) 之后)决定了 \(w^{'}\) 的一段怎样的值域,还要取决于 \(a_{i}\) 的取值。
一个显然的性质是:\(w^{'}\) 的值域上下界均关于 \(a_{i}\) 单调不增。
如果 \(a_{i}\) 过小,\(K^{'}\) 可能小于 \(w^{'}\) 的下界;如果 \(a_{i}\) 过大,\(K^{'}\) 可能大于 \(w^{'}\) 的上界。
我们希望字典序尽量小,即 \(a_{i}\) 取一个使得 \(K^{'}\) 在 \(w^{'}\) 值域内的最小值即可;由于先前的限制,这样的 \(a_{i}\) 一定存在,且是以最优解存在。(所以我们不需要考虑上界;上界一定满足条件)
根据上述类似数学归纳法的算法流程,合法且字典序最小的序列被唯一确定。
时间复杂度 \(O(T\sqrt{k}\log{k})\)。

浙公网安备 33010602011771号