2 条题解

  • 0
    @ 2025-1-31 20:17:48

    OU 瑞平:你这玩意跟我那个做法感觉没啥区别啊,唯一的区别可能是,常数变大了

    写这篇题解的人真是太不牛了。

    考虑对原树进行 Top Cluster 分块,这可以将原树的边集不重不漏划分为 O(n)\mathcal O(\sqrt{n}) 个大小为 O(n)\mathcal O(\sqrt{n}) 的块。我们先求出 LCA 为 uu 的所有答案,然后做树上前缀和即可。

    对于单点 uu,考虑引起贡献的两个点。如果 uu 不是这棵簇的界路径上的点,那么引起贡献的 x,yx, y 均与 uu 在同一棵簇内,可以直接 O((n)3)\mathcal O(\left(\sqrt{n}\right)^3) 复杂度内暴力解决。

    否则,下面的所有点 uu 都在某棵簇的界路径上。我们考虑这样的问题:对于当前节点 uu,有一个数组 ff,其中 fSf_S 表示满足 vSubtree(u)v \in \textrm{Subtree}(u),且 uvu \sim v 路径上的所有出现过点权集合为 SS 的种类数。如果给出 ff,且仅统计所有 vSubtree(u)v \in \textrm{Subtree}(u) 的贡献,那么答案是

    S=02k1fSuSau\sum_{S=0}^{2^k-1} f_S \prod_{u \in S} a_u

    我们可以换一个角度理解这个事情,假设我们在做 FWT,那么我们在 ff 每一维做一个神秘的线性变换到 ggg0f0+auf1,g1au(f0+f1)g_0 \gets f_0 + a_uf_1, g_1 \gets a_u(f_0 + f_1)。答案是 f0f_0。这同样可以 O(k2k)\mathcal O(k \cdot 2^k) 计算答案。

    我们假设这棵簇真的就长得像一条链,那么每次 ff 向上的时候只需要把所有 cx∉Sc_x \not\in Sff 值加到 fS{cx}f_{S \cup \{c_x\}} 里,并且对原 fSf_S 清零。即可。这条链的长度是 O(n)\mathcal O(\sqrt{n}) 的,但是有意义的合并只会发生 kk 次,而 2k+2k1++1=O(2k)2^k + 2^{k-1} + \dots + 1 = \mathcal O(2^k),所以复杂度依旧是 O(k2k)\mathcal O(k \cdot 2^k)

    现在这棵簇长得不像一条链了!但是在 uu,我们可以枚举所有簇内的 xx(其实是包括 uu 的)满足 xx 的最近簇路径节点为 uu,这时我们再枚举簇外节点 yy 即可补全贡献。所有 yy 的信息被携带在数组 hh 里,我们只要让 TT 表示 uuxx 路径上所有出现颜色集合,那么 hTh_T 事实上就是所有可能 yyxx 的路径答案之和。只要计算出 hh,贡献是容易简单统计的。

    最后,答案唯一可能出现问题的是所有的簇界点,因为它可能同时是若干个簇的上界点,我们在 FWT 暴力合并不同簇的 ff 数组时加入贡献即可。

    时间复杂度即为 O(nn+k2kn)\mathcal O(n\sqrt{n} + k2^k\sqrt{n})

    信息

    ID
    116
    时间
    9000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    130
    已通过
    14
    上传者