2024.11.26总结

本文于 github 博客同步更新。

A:

学生大战一个半小时未果,结束前半小时发现是打表找规律。

就是分讨一下,首先大于 \(1\) 的数不能超过两个,若有两个则其中一个必定为 \(2\),然后看一下 \(1\) 的个数是不是 \(3\) 的倍数即可。

B:

拆贡献,分为 \(u\rightarrow lca\)\(lca\rightarrow v\),前者需要求出 \(S[1, i]\) 作为子序列出现了多少次,后者需要求出 \(S[i, |S|]\) 作为子序列出现了多少次,两者是对称的。

对于每个 \(u\),求出 \(u\) 到根的路径上有多少个子序列为 \(S[l, r]\),记为 \(f_{u, l, r}\),这个数组容易在 \(O(n |S|^2)\) 内的时间预处理。

查询时考虑 \(f_{u, 1, i}\) 代表的 \(S[1, i]\)\(u\)\(lca\)\(lca\) 父亲到根两条路径之间的分布,比如 \(u\)\(lca\) 上有 \(S[1, j]\)\(lca\) 父亲到根有 \(S[j+ 1, i]\),后者预处理时已经被求出来了,因此可以容斥掉这部分贡献,总时间复杂度 \(\mathcal O(n \log n + (n + q) |S|^2)\)

C:

启发式分治,每次找到区间最大值 \(i\),那么区间内包含 \(i\) 的合法区间不超过 \(\log\) 个,然后每次选择 \(i\) 左右两侧较短的一侧,枚举区间和,判断另一端点是否在区间内,直接转移即可。

需要一开始将所有前缀和塞到 \(map\),不能分治时现塞,因为区间长度无法保证。

D:

无法战胜。

posted @ 2024-11-26 20:21  鳶一折紙  阅读(29)  评论(3编辑  收藏  举报