CSP-S2023 题解
CSP-S 2023 题解
密码锁
发现总状态数只有 \(10^5\) 个,枚举 \(O(n)\) 暴力判断即可,复杂度 \(O(10^5 n)\)。
或者每一个状态只对应了 \(81\) 个状态,枚出来,取交集即可,复杂度 \(O(81 n)\)。
消消乐
好的,来一波抽象做法 QwQ
我看到这道题的第一眼:这不就是 QOJ 6504 Flower's Land 2 吗。
于是考虑对每一个元素赋一个矩阵 \(M_i\),奇偶分开赋正逆矩阵,例如 aaa
就为 \(M_a, M_a^{-1}, M_a\) 或者 \(M_a^{-1}, M_a, M_a^{-1}\)。
于是一个区间合法当且仅当 \(\prod M_i = I\),这可以考虑矩阵满足结合律,但是不满足交换律。
其实换成任意一种满足结合律,但是不满足交换律的东西来都可以维护。
暴力枚举是不可取的,考虑前缀和,则合法当且仅当 \(pre_r \times pre_{l - 1}^{-1} = I\)。
考虑两边同时乘上 \(pre_{l - 1}\),那么合法当 \(pre_r = pre_{l - 1}\)。
于是用一个桶或者 map
记录一下数量即可求出答案,注意需要开 long long
。
如果是 \(2 \times 2\) 的矩阵,求逆的话就别用高斯消元了,推一下式子即可得到:
或者可以用自逆矩阵,但我声称那没必要。
代码:云剪贴板 - 洛谷
然而这还不够优秀,(其实可以另开炉灶),我们基于矩阵继续优化。
其实不难发现,对于一个合法的区间,\(\prod M_i\) 可以被划分为若干个合法区间。
如果我们使得每一个合法区间最小,那么划分可以证明是唯一的。
例如 abbacddc
就可以分为 abba
和 cddc
两个区间。
于是对于每一个 \(i\),考虑找到最后一个 \(pre_i = pre_j\) 的 \(j\) 记为 \(t_i\)。
我们考虑如何快速的递推求出 \(t_i\)。
如果我们已经求出了 \(t_{i - 1}\),也就是 \(\prod_{t_{i - 1} \le k \lt i} M_i = I\) 那么对于 \(i\) 来说,我们需要找到前面的某一个 \(j\) 使得。
发现 \(t_i - i\) 这个区间一定形如 \(x (某合法串) \cdots (某合法串) x\),于是初始答案为 \(x = t_{i - 1}\),我们不断的跳 \(t_{x - 1}\) 直到 \(S_x = S_i\) 为止,那么此时一定满足 \(t_i - i\) 是合法的且是最小的,利用神秘复杂度分析可以得知这就是 \(O(n |\Sigma|)\) 的。
最后 \(O(n)\) 的扫一遍,记 \(f_i\) 表示以 \(i\) 结尾的合法串的个数,\(f_i = 1 + f_{t_i - 1}\),答案为 \(\sum f_i\)
代码在剪切板底部:云剪贴板 - 洛谷
结构体
超级模拟,利用 object id
完成模拟即可。
只是注意 addr
的 fix
与对应的 align
种树
显然二分答案,然后考虑如何检查。
发现可以快速的求解出最晚能放置的时间 \(f_x\),由于树形结构存在依赖,考虑 \(O(n)\) 的更新一次:\(f_x = \min(f_x, \min_{y \in Son(x)}f_y - 1)\)。
然后将 \(f_x\) 排序,存在合法的操作序列当且仅当 \(\forall i, i \le f_i\)。
现在就可以得到一个 \(O(\log V (n \log V + n \log n))\) 的抽象做法了(我的考场做法,还跑得挺快,自测数据用了 500ms)
其实可以 \(O(n)\) 的判断,优化如下:
可以发现树生长的过程是一段一次函数和一段二次函数,那么将断点预处理一下,每次可以 \(O(1)\) 的求解一个方程,解出最晚能放置的时间 \(f_x\),这部分就是 \(O(n)\) 的了。
发现合法的序列只需要判断 \(\le n\) 的部分即可,因为对于 \(f_i \ge n\) 的时候存在 \(i \le n \le f_i\),一定满足条件。
所以可以开一个 \(O(n)\) 的桶,前缀和一下数量 \(c_i\),满足 \(\forall i, c_i \le i\) 即合法,这样就可做到 \(O(n)\)。
于是得到了一个 \(O(n \log V)\) 的优秀做法。