QOJ.ac

QOJ

Type: Editorial

Status: Open

Posted by: Anonymous

Posted at: 2026-09-11 20:27:18

Last updated: 2026-09-11 20:28:16

Back to Problem

$O(n^3)$ 题解 by ChatGPT

官方题解只能做到 $O(n^4)$ / $O(n^3 \log n)$?玩的太差了。这题可以做到 $O(n^3)$ 时间、$O(n^2)$ 额外空间。官方题解最后给出的复杂度是 $O(n^3\log n)$;进一步优化的关键是:二维卷积的两个操作数往往很不均衡,不能每次都按较大的一方整体做 NTT,而应当使用分块的不等长卷积,再对整棵树统一分析复杂度。(QOJ)

下面先解决计数不重不漏的问题,再说明怎样真正去掉这个对数。

将可行性压缩成唯一的二维状态

题目统计的是合法的二元组 $(S,\boldsymbol c)$ 的数量,其中 $\boldsymbol c$ 是整棵树的缤纷度序列。不同染色只要产生相同的 $\boldsymbol c$,就不能重复计算。 因此,不能直接对染色方案做普通树形 DP。

考虑固定一棵子树内的 $S$ 和缤纷度序列。记这棵子树一共出现 $x$ 种颜色,再定义 $z$:为了实现这个二元组,最少需要在子树的严格祖先中提供多少种不同颜色。暂时允许在子树上方放置任意多个虚拟祖先,从而使这个定义不受当前深度影响。这就是官方题解中用于判定可行性的贪心状态。(QOJ)

为什么只记录最小值 $z$ 就够了?因为颜色的具体名字没有意义。如果某种实现需要祖先提供 $z$ 种颜色,那么对于任意给定的、至少包含 $z$ 种颜色的祖先颜色集合,都可以通过重命名得到合法实现。另外,把子树内某些原本不在祖先中出现的颜色,改成祖先中尚未使用的颜色,也不会破坏原有约束。因此,可行性只取决于祖先能否提供足够多的不同颜色,不必记录一个复杂的可行集合。

定义 $F_u[x,z]$ 为:子树 $u$ 内有多少个不同的二元组 $(S_u,\boldsymbol c_u)$,其根的缤纷度为 $x$,最少需要祖先提供的颜色数恰好为 $z$。每个二元组只有一个确定的最小值,所以只会进入一个状态。最后的答案就是 $\sum_x F_0[x,0]$,因为整棵树没有祖先。

现在推导如何合并。假设选定了每个儿子的一种状态 $(x_i,z_i)$。先把结点 $u$ 自己也看成一个状态为 $(1,1)$ 的分量:它有一种颜色,而这类颜色暂时被标记为“必须由边界提供”。此时边界可以理解为“$u$ 加上它的严格祖先”,待合并结束后再处理 $u$ 是否属于 $S$。

对所有分量,包括这个 $(1,1)$,记 $A=\sum_i x_i$、$B=\sum_i z_i$、$L=\max_i x_i$、$M=\max_i z_i$,并记 $D=A-B$。如果合并后的不同颜色数为 $X$,显然必须有 $L\le X\le A$。此时需要边界提供的最少颜色数为

$$ Z_{\min}(X)=\max\{M,\ B-(A-X)\}=\max\{M,\ X-D\}. $$

这个结论是整个算法的核心,需要同时证明必要性和充分性。

必要性很直接。某个分量需要 $z_i$ 种边界颜色,合并后当然不能少于 $M$ 种。另一方面,从各分量颜色完全不同的情况出发,总颜色数由 $A$ 降到 $X$,一共消除了 $A-X$ 次重复计数;边界颜色的重复计数最多也只能减少这么多,因此还必须有 $Z\ge B-(A-X)$。

充分性可以直接构造。令 $Z=\max{M,X-D}$,准备 $X$ 种颜色,其中 $Z$ 种作为边界颜色。由于 $M\le Z\le B$,可以让各分量分别选择 $z_i$ 种边界颜色,并使这些选择的并集覆盖全部 $Z$ 种颜色。余下的 $X-Z$ 种非边界颜色,要放入各分量剩余的颜色位置中;这些位置共有 $A-B=D$ 个,而 $X-Z\le D$,所以足够。各分量内尚未填满的位置,再使用该分量尚未使用的颜色补齐即可,因为始终有 $x_i\le X$。某些原本不必使用边界颜色的位置最终也使用了边界颜色,并不会破坏合法性。

处理完这些分量后,再决定 $u$ 是否属于 $S$。

当 $u\in S$ 时,$u$ 的颜色也必须由严格祖先提供,最终状态就是 $(X,Z)$。当 $u\notin S$ 时,可以让 $u$ 自己提供其颜色,严格祖先只需提供剩下的 $Z-1$ 种,最终状态为 $(X,Z-1)$。这也已经最优,因为加入一个结点最多只能多提供一种颜色。根结点 $0$ 不允许属于 $S$,因此只保留后一种转移。

这里增加的是一个二元组的计数,而不是颜色对齐方式的数量。对于固定的各儿子二元组、固定的 $X$ 和固定的 $u\in S$ 与否,父亲处的二元组已经唯一确定;上面的构造只负责证明它存在。

用三张二维表代替四维状态

如果直接维护 $(A,B,L,M)$,状态维数还是太高。但对于固定的一组儿子状态,所有合法的 $(X,Z_{\min}(X))$ 都在一条折线上。

当 $X$ 从 $A$ 减小时,状态先从 $(A,B)$ 沿对角线走到 $(D+M,M)$,再沿水平线走到 $(L,M)$。其中 $L\le D+M\le A$:前一个不等式来自对每个分量都有 $x_i=(x_i-z_i)+z_i\le D+M$。

因此,我们不需要知道四元组的完整联合分布,只需要知道三个端点各自的分布。这正是官方题解的三组二维 DP。(QOJ)

记第一张表为 $P^{(0)}[a,b]$,统计 $(\sum_i x_i,\sum_i z_i)=(a,b)$ 的儿子组合数;第二张为 $P^{(1)}[d,m]$,统计 $(\sum_i(x_i-z_i),\max_i z_i)=(d,m)$ 的组合数;第三张为 $P^{(2)}[\ell,m]$,统计 $(\max_i x_i,\max_i z_i)=(\ell,m)$ 的组合数。

三张表分别独立合并儿子。第一张使用两个坐标都取和的卷积,第二张使用第一维取和、第二维取最大值的卷积,第三张使用两维都取最大值的卷积。结点自身的虚拟分量对应初始化 $P^{(0)}[1,1]=1$、$P^{(1)}[0,1]=1$、$P^{(2)}[1,1]=1$。

注意,合并儿子期间只维护这些统计量,不要为中间合并结果枚举颜色数 $X$。那些中间结果并不对应原树中的结点,枚举它们会引入题目没有要求记录的信息,导致重复计数。只有全部儿子合并完毕后,才生成当前结点的 $X$。

接下来用差分恢复所有折线。为了避免拐点重复,对角段包含起点 $(A,B)$、不包含拐点 $(D+M,M)$;水平段则包含从 $(D+M,M)$ 到 $(L,M)$ 的两个端点。

建立两张差分表 $E,H$。一个权值为 $w$ 的儿子组合,对对角差分产生 $E[A,B]\mathrel{+}=w$、$E[D+M,M]\mathrel{-}=w$,对水平差分产生 $H[D+M,M]\mathrel{+}=w$、$H[L-1,M]\mathrel{-}=w$。因此,利用三张统计表,可以直接得到 $E[x,z]=P^{(0)}[x,z]-P^{(1)}[x-z,z]$ 和 $H[x,z]=P^{(1)}[x-z,z]-P^{(2)}[x+1,z]$,不存在的下标均视为零。

然后按 $x$ 从大到小扫描,分别执行 $E[x,z]\mathrel{+}=E[x+1,z+1]$ 和 $H[x,z]\mathrel{+}=H[x+1,z]$。恢复后,$G_u[x,z]=E[x,z]+H[x,z]$ 就是合并所有分量后,颜色数为 $x$、最小边界颜色数为 $z$ 的组合数。

对于非根结点,每个 $G_u[x,z]$ 分别加入 $F_u[x,z]$ 和 $F_u[x,z-1]$;根结点只加入后者。因为虚拟分量保证 $z\ge1$,不会出现减到负数的问题。特别地,非根叶子的状态恰好是 $F_u[1,0]=F_u[1,1]=1$,根为唯一结点时答案为 $1$。

至此,正确性已经闭合:每个儿子二元组进入唯一状态,每组儿子二元组对每个合法的 $X$ 恰好贡献一次,而三张表的差分叠加只是对这些贡献的线性重排。

将总时间复杂度降到 $O(n^3)$

设一次合并的两部分分别包含 $p,q$ 个原树结点。不妨通过交换操作数保证 $p\ge q\ge1$。它们的二维表分别至多有 $O(p^2)$ 和 $O(q^2)$ 个位置。

先处理带最大值的两种卷积。

对于两维都取最大值的卷积,做二维前缀和即可。若 $\widehat U[a,b]=\sum_{i\le a,j\le b}U[i,j]$,则合并后有 $\widehat W[a,b]=\widehat U[a,b]\widehat V[a,b]$,再做二维差分恢复 $W$。这一步只需 $O(p^2)$ 时间。

对于一维取和、一维取最大值的卷积,只对最大值那一维做前缀和。定义 $\overline U[d,t]=\sum_{m\le t}U[d,m]$,则 $\overline W[d,t]=\sum_{a+b=d}\overline U[a,t]\overline V[b,t]$。也就是说,对每个阈值 $t$ 做一次普通的一维卷积,再对 $t$ 做差分。

阈值共有 $O(p)$ 个,每次卷积的两个长度分别为 $O(p)$ 和 $O(q)$。即使用朴素卷积,这部分也只有 $O(p^2q)$;使用不等长快速卷积,还可以降到 $O(p^2\log(q+1))$。

真正需要仔细处理的是第一张表的二维普通卷积。直接枚举两张表需要 $O(p^2q^2)$,而直接把它们都补到较大的尺寸做二维 NTT,则需要 $O(p^2\log(p+1))$。后者的问题是:当 $q$ 很小时,对数仍然取决于 $p$。

解决方法是将较大的二维数组划分成边长为 $q+1$ 的方块。块数是 $O((p/q)^2)$,每块分别与较小的完整数组做二维卷积,最后按照该块的原始坐标,把结果平移并累加。每块的两个操作数都只有 $O(q)\times O(q)$ 大小,卷积只需 $O(q^2\log(q+1))$,因此整次合并的时间为 $O(p^2\log(q+1))$。这正是不等长高维卷积去掉额外对数的关键。(QOJ)

二维卷积也不要求专门编写二维 NTT:对每块选取足够大的进制,将两个坐标编码为一个指数,使乘法时较低位不产生进位,就能转成长度为 $O(q^2)$ 的一维卷积。重要的是,编码和补零的尺寸由较小的一方决定,而不是由 $p$ 决定

同样的分块方法用于一维卷积,可以把长度为 $O(p)$ 和 $O(q)$ 的卷积做到 $O(p\log(q+1))$,从而得到前面第二种合并的快速实现。实际实现时,小规模直接暴力、大规模才使用 NTT 即可。

现在分析整棵树。由于 $\log(q+1)=O(q)$,以上三种合并的时间都不超过 $O(p^2q)$。把每个结点自身视为一个大小为 $1$ 的部分,并把逐个合并儿子的过程展开,就得到一棵以原树结点为叶子的二叉合并树。对于一次合并,有

$$ p^2q\le \frac{(p+q)^3-p^3-q^3}{3}. $$

对所有合并求和,右侧的内部部分全部抵消,只剩根处的 $n^3$ 和叶子处的常数项,因此所有卷积的总耗时为 $O(n^3)$。

此外,在规模为 $s_u$ 的子树上,坐标变换、差分恢复和生成 $F_u$ 都只需 $O(s_u^2)$ 时间;总计 $\sum_u O(s_u^2)=O(n^3)$。所以完整算法的时间复杂度确实是 $O(n^3)$,而不是 $O(n^3\log n)$

空间上,不必永久保存所有结点的 $F_u$。深度优先处理,每个儿子的表合并进父亲的三张统计表后立即释放。任意时刻保留的各部分对应互不相交的结点集合,设其大小为 $t_1,t_2,\ldots$,则 $\sum_i t_i\le n$,从而 $\sum_i t_i^2\le n^2$;再加上常数张卷积及差分临时表,额外空间为 $O(n^2)$

最后需要区分两种“最优”:在显式计算每棵子树全部 $F_u[x,z]$ 的框架中,链上的非根子树确实可以具有 $\Theta(s_u^2)$ 个非零状态,总状态数达到 $\Theta(n^3)$,所以这里已经做到了该框架的渐进最优。但这只是这个 DP 框架的下界,不能把它误写成原计数问题对所有可能算法的 $\Omega(n^3)$ 下界。

Comments

No comments yet.