「ZJOI 的部分题解整理」


会把之前的 ZJOI 题解(陆续更新) + 新的 ZJOI 题解整合在一起。

水平有限,所以仅有一部分题解。

从 ZJOI2016 开始,之前的题如果有时间再补上吧。

题目在 uoj/loj 上都可以找到。


「ZJOI2016」旅行者

网格图分治,每次选 \(n, m\) 中较大的进行分割。

对于跨越分割线的询问,枚举分割线上的点求最短路。

\(S = n\times m\),复杂度 \(O(S\sqrt{S}\log S)\)


「ZJOI2016」小星星

\(f_{x,i,s}\) 表示把 \(x\) 映到 \(i\) 上,子树内所有映到 \(s\) 上的方案数,复杂度 \(O(n^2\times 3^n)\)

发现是子集卷积,考虑对占位多项式 \(g_{x,i,t,s} = [popcount(s)=t]\times f_{x,i,s}\) 进行 fwt,中途不需要反演回来,复杂度 \(O(n^4\times 2^n)\)

注意到对于某一个 \(x\),只有当 \(t = size(x)\)\(g_{x,i,t,s}\) 才有值,所以可以省掉一维,复杂度 \(O(n^3\times 2^n)\)

用容斥可以推得类似的做法。


「ZJOI2016」大森林

将树的序列看作时间轴,从左往后扫描,在 \(l\) 处加入操作,在 \(r + 1\) 处弹掉操作。

可以通过简单转化保证操作 1 对应的树全部含点 \(x\),那么 0 操作的区间不再重要。

考虑操作 1 对应的修改,即将一些点的父亲全部修改为某个点,可以通过建虚点 + lct 完成这一操作。

注意询问不能直接查路径上的实点数量。


「ZJOI2016」线段树

\(dp(i,l,r,x)\) 表示第 \(i\) 次操作以后,\(a'_{l\dots r}\leq x\)\(a_{l-1}>x,a_{r+1}>x\) 的概率。即 \(\leq x\) 的极长区间。

注意到转移时 \(x\) 并没有影响,\(x\) 只影响初态 \(dp(0,l,r,x)\)

且已知 \(dp\) 后求答案只需要 \(\sum_{x}dp(q,l,r,x)\)\(dp(q,l,r,\max\{a_i\})\),因此可以去掉 \(x\) 这一维。

时间复杂度 \(O(n^3)\)


「ZJOI2017」仙人掌

可以将问题转化成 “树上不交链划分”,这里的不交指没有公共边。

考虑求出每个点 \(x\) 的贡献,发现只与 \(x\) 的度数 \(deg(x)\) 有关,记作 \(f_{deg(x)}\)

预处理 \(f\) 即可。


「ZJOI2017」树状数组

正常做只有当 \(x\leq y\)\(x\to y\) 产生贡献,反着做即 \(x\geq y\)\(x\to y\) 产生贡献,即后缀和(注意特判 \(0\))。

那么等价于查询 \(A_{l-1} = A_r\) 的概率,树套树即可(再次强调,注意特判 \(l=1\))。


「ZJOI2017」线段树

询问可以拆成两条链 \(l\to lca\)\(r\to lca\)。可以考虑使用倍增找到询问点 \(u\) 的位置,并维护 “被定位的点” 的信息。


「ZJOI2018」历史

考虑每个点 \(x\) 的贡献,记 \(sum_x=\sum_{y\in subtree(x)}a_y\),只需要判断是否存在一棵子树的 \(sum_{ch} > \frac{sum_x}{2}\)(或者 \(a_x > \frac{sum_x}{2}\))。

注意到所有点的上界可以同时取到,因此这就是答案。那么只需要动态维护每个点满足 \(sum_{ch} > \frac{sum_x}{2}\) 的重儿子 \(ch\) 即可。

考虑像 lct 一样每条重链用一棵平衡树维护,此时内层 splay 森林的复杂度分析一样,轻重边切换的复杂度分析需要稍微改改,还是可以证得 \(O(n\log n)\) 的复杂度。

(这个思路还可以用于动态维护重链剖分,即今年北大集训的 D3T3)。


「ZJOI2018」胖

考虑二分每个点 \(x\) 所能更新的区间 \([l_x, r_x]\) 对应的 \(l_x, r_x\)

需要找到 “能在 \(x\) 到达之前到达二分点 \(mid\)\(y\),距离 \(mid\) 的最短距离”,可以预处理 st 表 + 二分查找。

时间复杂度 \(O(n\log^2n)\),此处认为 \(n, \sum K\) 同阶。注意点的贡献不要算重。

本题存在 \(O(n\log n)\) 的做法,详见 https://blog.csdn.net/zxin__/article/details/82925838。


「ZJOI2019」线段树

考虑 dp:定义 \(dp(0/1, 0/1, x)\) 表示 x 的祖先结点是否有 tag,x 本身是否有 tag,这 4 种情况分别对应的方案数。

观察 dp 的转移,发现只有线段树上单点修改/子树修改,单点询问/子树询问。

直接维护一下线段树上的 单点 dp 值/转移矩阵 与 子树 dp 值/转移矩阵 即可。

时间复杂度 \(O(n\log n)\)


「ZJOI2019」Minimax 搜索

记根对应权值为 \(rt\),尝试求出 \(\max_{i\in S}|i-w_i|\leq k\) 的集合数。首先特判集合中包含 \(rt\) 的情况。

给定 \(k\),可以求出每个 \(> rt\) 的叶子是否可以 \(< rt\),每个 \(<rt\) 的叶子是否可以 \(> rt\)

\(f(x)\) 表示只把 \(> rt\) 的改小使 \(w_x\) 变小的集合数,记 \(g(x)\) 表示只把 \(< rt\) 的改大使 \(w_x\) 变大的集合数,可以 dp。

发现每一个 \(k\) 都要重新 dp,可以按 \(k\) 从小到大的顺序进行动态 dp。


「ZJOI2019」开关

\(q_i=\frac{p_i}{\sum p_i}\)

一种推导方法是使用集合幂级数:

\(f_S\) 表示当前开关状态为 \(S\),到达终态的期望步数。有转移:

\[\begin{cases} f_S &= 1+\sum_{i=1}^{n}f_{S\ \rm{xor}\ 2^i}\times q_i\\ f_0 &= 0 \end{cases} \]

\(I\) 表示全 \(1\) 的序列,给不满足转移的 \(f_0\) 加上偏移量 \(k\),可得卷积式:

\[F\otimes Q + I = F+k \]

\(fwt(F)\times fwt(Q-1)=fwt(k-I)\)

由于 \(fwt(F)_S = \sum_{T}(-1)^{|S\cap T|}f_T\),得:

\[\begin{aligned} fwt(Q-1)_S&=\sum_{i\not\in S}q_i-\sum_{i\in S}q_i-1\\ fwt(k-I)_S&=-\sum_{T\subseteq S}(-1)^{|T|}\times 2^{n-|S|}+k \\ &=-2^{n-|S|}\times\sum_{i=0}^{|S|}{|S|\choose i}(-1)^i+k \\ &=k-[S = \empty]\times 2^n\\ \end{aligned} \]

因此 \(fwt(Q-1)_{\empty} = 0\),推得 \(fwt(k-I)_{\empty} = k-2^n=0\),解得 \(k = 2^n\)

\(S\neq \empty\) 时,有 \(fwt(F)_S = \frac{fwt(k-I)}{fwt(Q-1)} = \frac{2^n}{\sum_{i\not\in S}q_i-\sum_{i\in S}q_i-1}\)

由于 \(ifwt(F)_S = \frac{1}{2^n}\sum_{T}(-1)^{|S\cap T|}f_T\)。则:

\[\begin{aligned} F_S &= \frac{1}{2^n}(\sum_{T\not =\empty}\frac{(-1)^{|S\cap T|}\times 2^n}{\sum_{i\not\in T}q_i-\sum_{i\in T}q_i-1} + fwt(F)_0) \\ &= \sum_{T\not =\empty}\frac{(-1)^{|S\cap T|}\times\sum p_i}{\sum_{i\not\in T}p_i-\sum_{i\in T}p_i-\sum p_i} + \frac{fwt(F)_0}{2^n} \\ &= -\sum_{T\not =\empty}\frac{(-1)^{|S\cap T|}\times\sum p_i}{2\sum_{i\in T}p_i} + \frac{fwt(F)_0}{2^n} \end{aligned} \]

如果已知 \(\frac{fwt(F)_0}{2^n}\),以 \(\sum_{i\in T}p_i\) 为状态作背包 dp 就可以 \(O(n\sum p)\) 算出 \(F\) 的某一项了。

注意到还有条件 \(F_0 = 0\),可以通过这个条件解出 \(\frac{fwt(F)_0}{2^n}\)

也可以用 EGF 推:

\(F(z) = \prod_{i=1}^{n}(\frac{e^{q_iz}+e^{-q_iz}}{2})\) 表示回到原状态的 EGF。

\(G(z) = \prod_{i=1}^{n}(\frac{e^{q_iz}+(-1)^{s_i}e^{-q_iz}}{2})\) 表示永不停止,按到终态的 EGF。

\(\hat F(z),\hat G(z)\) 分别是 EGF 对应的 OGF,则 \(\frac{\hat G(z)}{\hat F(z)}\) 表示终态停止的 OGF,答案即为 \((\frac{\hat G(z)}{\hat F(z)})'|_{z=1}\)

\(F(z)=\sum a_k e^{kz}\),则 \(\hat F(z) = \sum \frac{a_k}{1-kz}\)(此时 \(k\) 形如 \(\frac{\sum_{i\in S}p_i}{\sum p_i}\))。同理 \(\hat G(z)=\sum\frac{b_k}{1-kz}\)。可以背包求出所有 \(a, b\)

由于 \((\frac{\hat G(z)}{\hat F(z)})'|_{z=1} = (\frac{\hat G'(z)\hat F(z)-\hat G(z)\hat F'(z)}{\hat F^2(z)})|_{z=1}\),但是 \(\frac{1}{1-z}\) 不能直接带,所以上下同乘 \(1 - z\)


「ZJOI2019」语言

维护端点在 \(x\) 子树内的链构成的并集,则贡献为链并集中 dfs 序在 \(x\) 之前的点数。

链并集可以通过 \(\sum dep_{a_i} - \sum dep_{lca(a_{i-1},a_i)}\) 计算,其中 \(a_i\) 为按 dfs 序排好的链端点。注意 \(a_i\) 是连成环的,也即还需要计算首尾的 lca。

链并集中 dfs 序在 \(x\) 之前的点数,可以把 \(x\) 加入其中并弹掉 \(x\) 之后的点。

于是线段树合并即可,时间复杂度 \(O(n\log^2 n)\)(求单次 \(lca\) 视作 \(O(\log)\))。

posted @ 2020-12-21 17:06  Tiw_Air_OAO  阅读(72)  评论(0编辑  收藏
把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end