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

  1. 一次三操作长度减少一半,除非是回文串
  2. 回文串答案可以做到 \(\frac{len+mid}{2}-1\),其中 \(mid\) 指中心同色段长度。
  3. 结束状态一定是回文串 \(\to\) 所有 12 操作可以在最前面做,然后跳 log 次三操作到回文串。

只关心做完 12 操作后的串,找询问区间完全包含的串统计答案。
枚举结束状态,倒着考虑。

先不考虑区间询问,我们需要解决以下问题:

  1. 预处理所有回文串的答案
  2. 找到回文串能跳到的串的答案

第 1 问可以用 manacher 直接预处理,显然取每个中心点的最长回文串最好。

第 2 问需要找到一个串“跳到”的所有串,即找到这个串前面最近的反串。这个可以把 \(S\)\(S\) 的反串放进一个 SAM 里,相当于找到“某个位置前/后 某个串的第一个出现位置”,即维护每个串的所有 \(endpos\)。在 link 树上线段树合并,然后找到 \(s[l,r]\) 对应的结点,线段树上二分即可。

容易发现,对于一个右端点 \(r\),我们跳最长的后缀回文一定更优,所以一共只需要跳 \(n\) 个串,复杂度是 \(O(n\log^2 n)\) 的。

考察区间询问的不同要求:

  1. 有些回文串超过了左右端点
  2. 跳回文串的时候,最长回文可能太长了

对于第 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\) 时刻。

  1. \([-s,-1]\)
  2. \([t-s,t-1],(t>=s)\) 还有 \([t-s,-1] 或 [1,t-1],(t<s)\)
  3. 注意到对于 \(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)\)

posted @ 2025-04-14 16:30  Cindy_Li  阅读(23)  评论(0)    收藏  举报