Day1
T1:
一开始的想法觉得每条路径推进到每个点都需要记录状态,但这样状态数太过冗余,不可做。
大胆猜想每次走一定直接到达终点。
首先若一条路径的起点或终点在另一条路径上,一定能够得到一个先后关系。
剩下的影响在于相交,首先能想到的是 能否为这些相交部分分配先后关系,使其达到可行。
一个想法是,既然这里的先后关系可以分配,那是否就不重要呢?
考虑第一种情况,首先出现环一定不可行,反之,直接走一个没有入度的囚犯,
容易发现,它是可走的,因为终点在该路径上的都有自它连出的一条边,
齐次,它走了之后不会影响任何路径,因为经过它终点的路径都已经走过了。
这样直接树剖,线段树维护度数,支持区间寻找最小值所在位置、区间 +1/-1 和 单点修改。
给了 4s 估计依旧会有点卡常。
Day2
T1:
考虑 B 和 C 操作对答案的优化,粘贴操作前的块一定都是 A 操作完成的,而粘贴下来的块是一个一模一样的子问题,先造出块然后剪切。
那么很自然地可以想到一个 \(O(n^3)\) 的 DP ,设 \(f_{l,r}\) 为完成了 \([l,r]\) 区间的最小代价。
每次转移将 \(l\) 左移,根据 在新串中有多少原串 计算答案。
此时的转移都是后缀跟原串匹配,将在前面的 A 操作放到最后做其实无关紧要,那么每一个有意义的转移都是在存在 border 的地方。
处理出每个子串 \(S_{[l,r]}\) 前面第一个相同的子串,可以帮助转移变成 \(O(n^2 \log n)\) 的。
这个预处理参考 kmp(雾
T2:
- 树分块, \(B \rightarrow A:\) 两块的编号,顺序无关,要求 \(\frac12 \left( \frac N B \right)^2 < 2^{20}\) ,解得 \(B \ge 7\) 。
- \(A \rightarrow B:\) 两块形态,块顶距离,哪个是祖先,在哪个点进入祖先。
- 注意到块形态一定是二叉树,可以用每个点的儿子个数表示形态, \(3^{2B-1}\) 。
- 在哪个点进入祖先,可用该点在块中的编号表示, \(2B-1\) 。
块顶距离的传递不可规避,最棘手的是形态,那么考虑形态的压缩。
- 块形态是二叉树,同时由分块的方式知,每棵子树的大小不超过 \(6\) ,又由子树间顺序不重要,可钦定左子树大小不小于右子树,如此可将树的总形态数压缩至 \(301\) 。
- 现在编号是非常稀疏的,也许能用来做点什么?
- 大的块无法使用小的块表示,但是小的块一定能在某一个大块中出现。如此,我们建立一些虚点,将所有块都按照 大小为 \(13\) 的块 的方式编号,可以将总形态数降至 \(66\) 。此时做到极致可以达到 \(30\) 位。
- 得到了优于赛时所有人的做法!
- 注意到我们并不关心树真正长什么样子,重要的是 \(x\) 到接壤点, \(y\) 到根 的距离,那么可以按照点到根/接壤点的距离继续压缩。
- 一个小 chick:我们能够用长度 \(\le n\) 的字符串表示 \(2^{n+1}-1\) 的信息,而不只是 \(2^n\) ,将长度也利用上就行。