2025年6月杂题集
2025年6月杂题集
- P5101 [JOI 2017 Final] 绳 / Rope
黑、结论。 - P5103 [JOI 2016 Final] 断层 / Geologic Fault
黑、旋转坐标系、时光倒流、树状数组。 - P9531 [JOISC 2022] 复兴计划
黑、贪心、动态 MST、增量构造、绝对值函数。 - P4224 [清华集训 2017] 简单数据结构
黑、复杂度分析、DP、暴力。 - P9962 [THUPC 2024 初赛] 一棵树
黑、凸包、可并堆、对顶堆。 - JZOJ7261 ODST / AT_agc022_e [AGC022E] Median Replace
(黑)、DP、矩阵乘法、不可删双指针。 - P6881 [JOI 2020 Final] 火灾 / Fire
黑、离线、扫描线、单调栈、笛卡尔树。 - P4003 无限之环
黑、网格图、黑白染色、费用流。
1. P5101 [JOI 2017 Final] 绳 / Rope
首先由于染色一次的费用是绳子的厚度,所以在一开始全部染好色一定最优。而题目要求染成两种颜色。
考虑一个结论,把所有颜色相同的极长段取出来,当且仅当除了首段和尾段外,其他所有段的长度都要为偶数,此时方案合法。
- 必要性:如果存在奇数段,那么中间的奇数段一定不能作为折痕,则永远无法折成长为二。
- 充分性:我们可以采取一下策略折成长度为二:先把尾段折成长为 \(1\),然后折倒数第二段的中点,不断这样操作下去。
所以考虑把绳子分成若干长度为 \(2\) 的色块,因为长为 \(2\) 的色块可以组成任意偶数。我们分类讨论第一个 \(2\) 色块以 \(1\) 开头还是以 \(2\) 开头即可。
枚举绳子包含的颜色 \(i\),如果一个色块包含 \(i\),那么这个色块染成 \(i\) 一定不劣,对于剩下的色块,我们求出现次数最多的颜色即可。
于是用一个桶记录每种颜色出现的次数,如果一个色块包含 \(i\),则把另一种颜色减掉。
随便用 set 维护一下就能做到 \(O(n\log n)\)。
2. P5103 [JOI 2016 Final] 断层 / Geologic Fault
首先时光倒流,我们从现在开始,每次把地面下沉,最后求出初始地面的深度即可。
把坐标轴逆时针旋转 \(45\) 度,即 \((x,y)\to (x-y,x+y)\)。那么初始地面位于 \((i,i)\)。
对于 \(D=1\),就把 \(x_i\le X\) 的 \(i\),对 \(y_i-2L\)。
对于 \(D=2\),就把 \(y_i>X\) 的 \(i\),对 \(x_i+2L\)。
发现 \(x,y\) 序列都是单调递增的,于是用树状数组维护 \(x,y\),修改时二分出断点即可。
复杂度 \(O(n\log ^2n)\)。
3. P9531 [JOISC 2022] 复兴计划
考虑对于一条边,不同的 \(x\) 时的边权形成一个以 \(w_i\) 为中心的绝对值函数。
可以猜想,一条边能作为最小生成树的边时的 \(x\) 一定是一段区间 \([l_i,r_i]\)。
所以我们可以依次从小到大加边,对于 \(w_i\) 的边,如果不连通则直接连,否则找到树上路径上 \(w_j\) 最小的 \(j\),则当 \(x\le \frac {w_i+w_j} 2\) 时 \(w_j\) 更优,否则 \(w_i\) 更优。于是令 \(r_j=\lfloor \frac {w_i+w_j} 2\rfloor,l_i=\lfloor\frac {w_i+w_j} 2\rfloor +1\),同时将树上 \(j\) 断开,\(i\) 连上。
于是这样就能求出所有 \([l,r]\)。然后再在 \(X\) 序列上二分,然后加上一次函数,维护高度的前缀和与斜率的前缀和即可。
复杂度 \(O(nm+q)\)。
4. P4224 [清华集训 2017] 简单数据结构
题目的修改有很多限制,首先是值域为 \(10^6\),其次每个数互不相同,还有每种数最多被操作 \(10\) 次。
考虑暴力 DP,由于第二问需要求开头的个数,所以设 \(f_{i,j}\) 表示 \(i\) 开头,长为 \(j\) 的上升倍数子序列的个数,显然 \(j< 20\),并且 \(f_{i,j}\) 在 int 范围内。
首先是预处理,需要枚举每个数的倍数然后再枚举 \(f_i\) 的每个位置转移,计算量均摊 \(m\log ^2m\)。
接下来考虑每一种操作:
- 往前面插入,枚举倍数转移即可,计算量均摊是 \(10\times m\log ^2 m\)。
- 在前面删除,直接删掉前面的 DP 值不会对后面造成影响。
- 在后面插入,这有点复杂,考虑把所有出现的因数拿出来,那么我们需要求出插入这个数后每个因数 \(f_{i,j}\) 的增量,于是设增量数组 \(t_{i,j}\),我们 \(d^2\) 枚举这些因数之间的转移,\(d\) 为因数个数。这部分的计算量为 \(d^2\log m\)。
- 在后面删除,与在后面插入同理。
对于询问,我们用一个桶 \(cnt_j\) 记录以 \(i\) 开头最长子序列为 \(j\) 时 \(i\) 的个数。
总计算量为 \(10\times m\log ^2m+10\times \sum d^2 \log m\)。不优化可以直接通过。
5. P9962 [THUPC 2024 初赛] 一棵树
首先考虑朴素的 DP,设 \(f_{i,j}\) 表示 \(i\) 子树内选了 \(j\) 个黑点。
- 对于每个点,先把所有儿子合并 \(f'_{x,i}=\min_{j\le i}f_{x,i-j}+f_{v,j}\)。
- 考虑自己选不选,\(f'_{x,i}=\min (f_{x,i},f_{x,i-1})\)。
- 加上到父亲的边权,\(f'_{x,i}\gets f_{x,i}+|2i-k|\)。
由于 \(|2i-k|\) 是凸的,于是 \(f\) 无论何时都是凸的。
因为凸性质,对于合并儿子的部分,可以记录 \(f\) 的差分数组与 \(f_{x,0}\),则合并就是将差分数组归并。这时就可以用可并堆记录差分数组,合并为 \(O(\log n)\)。
考虑怎样加边权,对于 \(i\le \lfloor k/2\rfloor\) 的部分,每个差分都加上 \(-2\);而对于 \(i=\lfloor k/2\rfloor+1\),当 \(k\) 为奇数时差分不变,否则差分加 \(2\);对于 \(i>\lfloor k/2 \rfloor+1\) 的部分,每个差分都加上 \(2\)。
所以把一个堆换成一组对顶堆,保证第一个堆大小不超过 \(\lfloor k/2\rfloor\),合并时分别把两个堆合并再调整堆的大小。由于每个点只会往堆里新增一个元素,且每个元素会从第一个堆往第二个堆里移动依次,所以复杂度是 \(O(n\log n)\)。
最终复杂度 \(O(n\log n)\)。
6. JZOJ7261 ODST / AT_agc022_e [AGC022E] Median Replace
首先考虑如何判定一个串是否合法,如果没有问号。考虑每次加一个字符进来,发现有以下最优策略:
*00+0 / *00+1 / *01+0消成*0。*10+1 / *01+1消成*1。- 其他情况不操作。
那么除了 01 与空串,其他情况都形如任意个 1 拼接上最多两个 0。
又发现,消除两个 0 只需要至少三个 1 即可,即 11100。所以大于三个 1 的情况都可以归类为等于三个的情况。
那么有这些状态:
| 结尾 0 数 \ 开头 1 数(x,y) | 0 | 1 | 2 | >2 |
|---|---|---|---|---|
| 0 | 空串 / 01 |
好 | 无 | 好 |
| 1 | 不好 | 无 | 好 | 好 |
| 2 | 无 | 不好 | 无 | 好 |
其中「无」表示长为奇数时不存在。
用空串的位置表示 01 是因为空串只有在位置 0 才出现,不会冲突,并且发现 01 的转移和空串是一样的,都是加 0 变成 \((1,0)\) 或加 1 变成 \((0,1)\)。
当 1 的个数大于二时默认长为奇数,因此都是「好」。
又发现当 1 的个数为二时,不是不存在就是「好」,因此可以考虑继续缩减状态,把大于 \(2\) 的也归类到等于 \(2\),得到下表。
| 结尾 0 数 \ 开头 1 数 | 0 | 1 | 2 |
|---|---|---|---|
| 0 | 空串 / 01 |
好 | 好 |
| 1 | 不好 | 无 | 好 |
| 2 | 无 | 不好 | 好 |
由此可以 \(O(n)\) 完成不带修改的版本。接下来考虑带修改的版本。
我们把转移写成矩阵,这样转移就可以合并了,直接套线段树是 \(O(Q\log QM^3)\)。题目的 \(L,R\) 类似双指针的移动,然而这个转移没有逆,考虑不带删双指针。
不带删双指针解决这样的问题:维护 \([L,R]\) 的信息,并且信息只有结合率且不能作差 ,\(L,R\) 分别不下降。
我们维护三个数 \(L,M,R\),以及 \((M,R]\) 的信息与满足 \(L\le i\le M\) 的区间 \([i,M]\) 的信息。求 \([L,R]\) 的信息由 \([L,M]\) 与 \((M,R]\) 相加得到。每次 \(R\) 右移时就直接移动,维护 \((M,R]\) 的信息。而当 \(L\) 右移时,如果 \(L\le M\) 则直接用维护好的信息,否则令新的 \(M=R\),记录 \([L,M]\) 这段区间的每个后缀的信息。
这样做的话,每个节点只作为 \(i\) 求了一次信息,也只作为 \(R\) 求了一次信息,复杂度因此是 \(O(n)\) 的。
再看这道题,直接用这个方法实现就可以做到 \(O(QM^3)\),无法通过。可以继续优化:考虑一次转移矩阵是 \(O(M)\) 的位置非空,而 \(O(M)\) 有值的矩阵乘 \(O(M^2)\) 有值的矩阵可以做到 \(O(M^2)\),具体地,类似于 \([i,j]\times [j,k]\to [i,k]\) 中,\(j\) 行只有第 \(k\) 列是有值的。
于是复杂度降为 \(O(QM^2)\)。
7. P6881 [JOI 2020 Final] 火灾 / Fire
首先把时间轴展开,那么就是在矩形上对若干个四十五度的直角三角形范围取最值。
转换一下,按权值从小到大加入这些三角形,每次覆盖之前染过色的位置。那么发现最后每种边权的染色区域形如一个平行四边形,并且与上一个大于它的位置 \(L_i\) 与下一个大于它的位置 \(R_i\) 有关。使用单调栈找到 \(L_i,R_i\)。
考虑暴力染这些平行四边形,如果可以用 \(\min(i-L_i,R_i-i)\) 次数染一个权值,那么根据笛卡尔树的性质,总次数是 \(O(n\log n)\) 的,证明同启发式合并的证明。
对于 \(i-L_i>R_i-i\),发现是对 \(R_i-i\) 个竖线区间染色,把询问离线下来,对于每一列都用差分打上加法标记。
对于 \(i-L_i\le R_i-i\),发现是对 \(i-L_i\) 个斜线区间染色,每个区间的左端点在同一列上。考虑转换一下坐标系,\((x,y)\to (x,y-x)\),那么就变成了对同一列修改,而且发现查询仍然是对于同一行。
对于 \(L_i\) 或 \(R_i\) 不存在的情况用同理染色即可,只是不需要打减法标记。对于 \(a_i\) 相同的位置我们指定 \(i\) 越大则权越大即可。
总复杂度 \(O(n\log ^2n)\) 但是跑得非常快,原因在于 \(\sum \min(i-L_i,R_i-i)\) 很难卡满。
8. P4003 无限之环
数据范围是 \(nm\le 2000\),题目的要求也比较复杂,所以考虑网络流。由于是网格图,先黑白染色。
考虑如何建图:
- 对于只有一条出边是容易的,存在连 0 边,邻边连 1 边,对边连 2 边。
- 对于 L 型,如果从上右转成了右下,那么可以看做把上换成了下,费用加一。如果是转 180 度,那么可以看做两条边都取反,费用各加一。所以对于存在的两边建 0 边,不存在的两边建 1 边。注意要确保不能让两条相对的边同时选,所以相对的边前面连同一个点,限制容量为 1。
- 对于 T 型,考虑对不存在的边连 2 边,两端连 1 边,中间连 0 边,让总费用先减 2 即可,这样就可以得到 0、1、2 的权值。

浙公网安备 33010602011771号