2023.11~2024.1 做题记录
越来越摆了。
* LOJ 3103
对于两字符串
首先容易观察到,设
把
可得,
假设我们可以维护出这些等差数列,可以证明,对于每个等差数列,只有其中的最小项和最大项可能成为答案。
借助后缀排序,我们可以在
(事实上这里也可以不使用后缀排序而使用 Z 函数)
事实上,对于同一个等差数列,我们只需要维护其最小项和最大项即可,所以整题可以在
CTT 2021 D4T1
看完题感觉极其神秘,先分析一下简单情况。
对于一个数
若
由于
当且仅当
只要
对
推理一下依然可得条件是
具体地,设
右边为
若此式满足,则左边等于:
我们考虑由于
若上式不满足,由
由上我们只需要找到
事实上,若存在半阶,设半阶为
而若
综上,我们只需求其阶然后除二用快速幂验证即可,复杂度
P5633 最小度限制生成树
胡策场上我用了和我的 JOISC 2023 D4T2 类似的做法,现在学学另一种做法。
这种做法主要利用:考虑一条边
若
这样我们可以对每条边求出其被删除时最小的增加值。直接把它们排序取前
这种做法较于我之前的做法需要更强的结论:
- 我之前的做法是直接按照顺序维护合并,因此需要维护边权和点权的差;
- 此做法在证明如下结论后强制按照边权顺序模拟合并,更好写:
- 结论:由于每次我们都会取二者路径上的
\max ,最终此边删去时的贡献不可能高于C 中的情况。
- 结论:由于每次我们都会取二者路径上的
线性筛 i^i 的做法
做法是:
-
对所有质数位置使用快速幂求值,这部分线性。
-
对于非质数位置,考虑设其最小质因子为
p ,设此数为pq ,那么有(pq)^{pq}=(p^p)^{q}(q^q)^p .由于
p\le \sqrt{n} ,因此设C=p^p ,可以直接使用类似 BSGS 的技巧求C^{1\cdots \sqrt{n}},(C^{\sqrt{n}})^{1\cdots \sqrt{n}} ,前半部分是平凡的.对于后者,由于我们是在枚举
q 时从小到大枚举p ,因此设C=q^q ,需要求的数形如:C^2,C^3,C^5,C^7,\cdots 是质数序列。考虑预处理出 prime gap 以内的
C^i ,就可以从前一个数转移到后一个。在合理数据范围内我们认为 prime gap 的上界约为
\Theta(\log^2 n) ,那么使用 BSGS 依然可以只预处理C^{1\cdots \log (n/q)} 。累加起来是经典的
\sum_{q=1}^n \ln(n/q)=\mathcal O(n) .
事实上也可以筛出
CTT 2021 D1T1
感觉这个问题非常朴素,不过要写代码,差评!
部分分的思考过程当时没写,现在也懒得写了,记一下做法。
我们设
不过事实上可能不能直接
据说还要卡卡才能过,懒得写代码了。
* P3642 [APIO2016] 烟火表演
一个显然的想法是 DP:我们设
我们观察
如果导火索可以被减到负数,那么对于任意子树可以只维护一个区间
但是很可惜导火索不能被减到负数,这样我们对于一个凸函数
我们发现后三种情况都是较为平凡的,第一种情况由于只加了一个常数所以也是可以维护的。
不难想到我们可以使用双堆维护凸函数的技巧维护之。对于此题,我们可以使用可并堆维护。
注意我们只能维护出所有的函数断点和无穷远处的斜率
启示:维护凸函数时不一定需要及时维护
** THUPC 2024 初赛 A
* THUPC 2024 初赛 B
应该算是经典 slope trick 题目了,但是我场上没看出来,太菜了。
有一个显然的
转移完了以后加上这个点的贡献是
事实上,我们可以归纳地证明
之后的部分分别相当于向差分数组中扔进一个
这可以直接使用平衡树维护,由于 Splay 合并总复杂度是
事实上还有一种实现方法只需要使用可并堆:
-
对每个子树维护两个对顶的可并堆
L,R ,其中L 维护前\min(siz_x,\frac{k}{2}) 个元素。 -
可以发现两个子树的
L,R 是可以合并的,合并完成后暴力弹出L 中的元素直到元素个数正确。由于每个元素只会有一次从
L 堆中弹出,所以总复杂度是\mathcal O(n\log n) 。 -
这样两部分分别转化为打加法标记,可以简单处理。
-
此做法唯一的问题是需要支持在堆上打加法标记,所以必须手写。
启示:遇到需要优化的 DP 先看看有没有凸性,出题人不一定有你想象得那么聪明。
THUPC 2024 初赛 C
一个相当漂亮的题目,可惜场上我是暴力推式子的。
正解就是考虑给这个模型找一个组合意义:
对于有一排无限长的灯,每个灯有
p 的概率亮起(否则熄灭)。设
pos_i 为第i 个亮起的灯的位置,那么x_i 就是pos_{i+1}-pos_{i} 的值。可以发现
x_i 的概率分布与原问题相等。
这样,原问题等价于
THUPC 2024 初赛 D
shaber 题。
首先考虑有一个显然的 2D-1D 区间 DP,使用树状数组优化之,可以直接做到
要做到
"找到最长回文前缀"在
THUPC 2024 初赛 E
考虑第二问怎么做。
假如所有
设存在某个时间点
对于
有了这个启发让我们再看看第一问,设当前枚举到
不难发现对
可以证明,对于所有
所以依然是维护集合
非常容易写出罚时,shaber 小 E。
THUPC 2024 初赛 K
考虑假如只有一个点是 o 那么先手必败,有恰好两个点是 oo 那么先手必胜。
若连通块大小为
只剩
oooo
----------------
o..
ooo
----------------
oo
oo
----------------
o.
oo
.o
----------------
o.
oo
o.
这几种。由于先手不可能在
换言之,先手需要尽可能让后手
I 可以,J/L 不行,O 可以,Z/S 都不行。
THUPC 2024 初赛 G
THUPC 2024 初赛 H
显然数字的长度不超过
考虑
对于每个数 set 维护其每次出现的位置;出现移除操作就在 set 中维护即可。
复杂度为什么是对的呢?我们知道,在每种长度的重建过程中数组都是有序的,所以总复杂度是单次线性,总共
而若当前删除了一个长为
THUPC 2024 初赛 I
我们考虑假如给定的串中有
考虑优化一下底层,我们确定一个
预处理出所有集合的过程可以直接暴力递推地对所有
计算一下可知,这种线段树式的二分思路应该已经走到头了。我们考虑优化后半部分。
对于所有长为
这样就可以用
然后把这
- 启示:底层也可以整体操作。
THUPC 2024 初赛 J
事实上,使用区间
- 对于
a_{1\cdots n} ,设M_{l,r}=\operatorname{mex}_{l\le i\le r} ,那么M 可以被表达为O(n) 个不交矩形的并,其中每个矩形中的数都相等。
证明的过程就是求出这
类似扫描线地,我们从
找到值为
上述所有东西可以使用 set 配合线段树上二分实现,复杂度
fo(r, 1, n) {
int l = r; lst[a[r]] = r, fix(1, a[r], r);
if(S.size() && prev(S.end())->v == 0) {
v[++tot] = *prev(S.end()), v[tot].yr = r - 1;
l = v[tot].xl, S.erase(prev(S.end()));
}
S.insert({l, r, r, 0, 0});
auto it = S.lower_bound({0, 0, 0, 0, a[r]});
if(it->v != a[r]) continue;
if(it->yl < r) v[++tot] = *it, v[tot].yr = r - 1;
int lb = it->xl, rb = it->xr; S.erase(it);
while(lb <= rb) {
int x = query(1, rb - 1), nxt = lst[x];
if(nxt >= lb)
S.insert({nxt + 1, rb, r, 0, x});
else {
it = S.lower_bound({0, 0, 0, 0, x});
if(it != S.end() && it->v == x)
v[++tot] = *it, v[tot].yr = r - 1, S.erase(it);
S.insert({nxt + 1, rb, r, 0, x});
}
rb = nxt;
}
}
for(auto z : S) v[++tot] = z, v[tot].yr = n;
// fix / query 分别是单点修改和查询最小的值 <= x 的位置
然后每个矩形的覆盖范围就恰好是一段区间,使用扫描线线段树维护即可。