2025.4.13 模拟赛
4.13 模拟赛
又是只有我不会 T1 场
但是 T1 思路确实比较有趣,以前没太见过。
控诉 T3 题面/kk
只存在于“过去”的指针怎么能在“现在”停掉呢/kk
cave
容易想到转化为 \(n\) 个人一起走,能否同时走到 \(R\)。
暴力就是枚举所有状态,建图 bfs 找最短路。
key:考虑不断合并,减少人数
两个点可以合并 \(\to\) 它们可以同时走到某个点,此时两个点合并成一个。
不妨令“某个点”为 \(R\),注意到有解当且仅当任意两个点可以合并。
\(O(n^3)\) 拓扑预处理状态 \((u,v)\) 走一步可达的状态,bfs 找到 \((R,R)\) 的路径。
构造时维护当前还有的点集,每次选两个点合并,其他点一起走。容易证明上界不超过 \(\frac{1}{2}n^3\),实测只能卡到 \(O(n^2)\) 左右。
recall
分析性质 + 大力字符串结构题
但是不会字符串结构,于是做不下去
于是学习了 SAM 和 PAM
- 一次三操作长度减少一半,除非是回文串
- 回文串答案可以做到 \(\frac{len+mid}{2}-1\),其中 \(mid\) 指中心同色段长度。
- 结束状态一定是回文串 \(\to\) 所有
12操作可以在最前面做,然后跳 log 次三操作到回文串。
只关心做完 12 操作后的串,找询问区间完全包含的串统计答案。
枚举结束状态,倒着考虑。
先不考虑区间询问,我们需要解决以下问题:
- 预处理所有回文串的答案
- 找到回文串能跳到的串的答案
第 1 问可以用 manacher 直接预处理,显然取每个中心点的最长回文串最好。
第 2 问需要找到一个串“跳到”的所有串,即找到这个串前面最近的反串。这个可以把 \(S\) 和 \(S\) 的反串放进一个 SAM 里,相当于找到“某个位置前/后 某个串的第一个出现位置”,即维护每个串的所有 \(endpos\)。在 link 树上线段树合并,然后找到 \(s[l,r]\) 对应的结点,线段树上二分即可。
容易发现,对于一个右端点 \(r\),我们跳最长的后缀回文一定更优,所以一共只需要跳 \(n\) 个串,复杂度是 \(O(n\log^2 n)\) 的。
考察区间询问的不同要求:
- 有些回文串超过了左右端点
- 跳回文串的时候,最长回文可能太长了
对于第 1 问,发现经过左右端点的回文串一定取最长的,可以 PAM 上倍增单独处理。中间的回文串还是取中心点最长回文,完全包含就是一个二维数点。
对于第 2 问,考虑对于一个右端点 \(r\),我们跳到的非回文串最多 $\log $ 个,可以全部找出来再二维数点。考虑我们只需要跳 \(len[fail[i]]*2 < len[i]\) 的串,对于一个右端点,我们可能跳的起点也是 $\log $ 个,还是可以 PAM 预处理。找到这些串后仍然是一个二维数点。
总复杂度 \(O(n\log^2 n+q\log n)\)
ion
神秘贪心题。
首先要注意到,某些 \(s_i\) 很大的 \(t_i=2\) 指针可能在第一次穿越前停掉(虽然这不合常理)。
考虑每个指针可以停掉的区间,然后就是一个二分图匹配问题,使用 Hall 定理解决。
设第一次穿越为 \(0\) 时刻,第二次穿越为 \(t\) 时刻。
- \([-s,-1]\)
- \([t-s,t-1],(t>=s)\) 还有 \([t-s,-1] 或 [1,t-1],(t<s)\)
- 注意到对于 \(t>=s\) 的三区间,必须拆成两个,干脆直接变成一二区间。对于 \(t<s\) 的,要么在 \([t-s,-1]\),要么还是拆成两个 \([-s,-1]\) 和 \([1,t-1]\)。
发现 \([1,t-1]\) 内有很多“全能”区间,容易合法,于是考虑在 \([1,t-1]\) 区间合法的情况下判断 \([-n,-1]\) 区间是否合法。
枚举有 \(c\) 个二区间放到 \([t-s,-1]\),注意到此时答案已经确定为 \(t-1+ct_1+ct_3+c\)。
同时,我们一定是把 \(s\) 最大的 \(c\) 个二区间放到前面,此时已经可以判断 \([1,t-1]\) 是否合法。
我们还需要考虑哪些三区间被拆成两个了。
根据 Hall 定理,当且仅当从 \(-1\) 枚举到 \(-i\),\(i-pre_i\ge 0\),即空位数不少于区间数。
考虑一个三区间被拆成两个,相当于对 $[t-s,-s] $ 区间加 \(1\)。于是宝宝贪心,找到当前可以加的区间中左端点最靠左的加上即可。
这样做是 \(O(n^3)\) 的。
考虑优化,枚举 \(t\) 显然是不太能少的,考虑优化掉枚举 \(c\) 的过程。
显然我们希望最小化 \(c\),也就是最小化拆成两个的三区间个数。
可不可以“能不拆就不拆”呢?
先认为所有一区间和三区间都在前面,二区间尽量放在后面。
仍然是从 \(-1\) 开始枚举,找到不合法的我们就必须拆三区间,此时如果后面没有空位了,我们就需要把一个二区间放到前面。放的和拆的区间都是确定的。
于是我们优化掉了枚举 \(c\)。找到拆的三区间可以用栈维护,数组可以先排好序再归并,复杂度 \(O(n^2)\)。

浙公网安备 33010602011771号