0%

CF 1100 E - Deconstruction Tree

题目大意

给一棵 nn 个点的树和一个空集合 SS 。每一步先找到当前树上编号最大的叶子 xx ,把 xx 加入 SS ,然后可以任选另一个叶子删掉。重复 n1n-1 次,问最后可能得到多少个不同的集合 SS

输入有多组测试,所有测试的 nn 之和不超过 21052\cdot 10^5 。答案对 998244353998244353 取模。

思路讲解

一句话

把树以最大编号点 nn 为根,非根点 yy 能被当前最大叶子 xx 转移到,当且仅当 need[y]<x<yneed[y] < x < y ;根节点单独处理,答案是所有能压住其它根分支的 dp[x]dp[x] 之和。

状态怎么想

集合 SS 的出现顺序一定是严格递增的一条链:当前最大叶子是 xx ,下一次进入 SS 的点只能是某个更大的 yy 。因此可以定义:

1
dp[y] = 最后一个进入 S 的点是 y 的方案数

初始状态不是 11 ,而是原树里的最大叶子:

1
2
start = max { v | degree(v) == 1 }
dp[start] = 1

这里有一个很容易错的坑:不能用“以 nn 为根后的有根树叶子”来找 start。如果根本身是原树叶子,它就是一开始的最大叶子。

非根转移

对一个非根点 yy ,设:

1
need[y] = y 的所有儿子子树里的最大编号

若当前最大叶子是 xx ,想让 yy 成为下一次最大叶子,需要先把 yy 下方所有分支删到不会冒出比 xx 更大的点。因此条件就是:

1
need[y] < x < y

所以转移可以一次性写成区间和:

1
dp[y] = sum dp[x], x in [need[y] + 1, y - 1]

这里不需要再扣掉 subtree(y)。因为如果 xxyy 的子树里,那么 xx 一定被 need[y] 覆盖,和 need[y] < x 矛盾。

根节点转移

nn 没有父亲方向,所以不能套普通点的公式。根的每个儿子对应一条根分支,定义:

1
branchMax[v] = max(v, subTreeMx[v])

也就是这个根儿子分支里的最大编号。设所有根分支最大值里的第二大值是 secondMax。想让根成为下一次最大叶子,只需要当前 xx 压住所有其它分支:

1
x > secondMax

所以根的贡献是:

1
dp[root] = dp.query(secondMax + 1, root - 1)

注意 secondMax 是门槛,不是前驱点。不要写成查 dp[secondMax],也不要查最大根儿子本身。

这次踩过的坑

  • start 要从原树度数为 11 的点里取最大值,不能从有根树叶子里取。

  • 维护最大值和次大值时,新最大值出现后,旧的最大值必须下放成次大值。

  • 根转移看的是第二大的根分支最大值,不是根的最大邻居,也不是最大分支的根儿子。

  • modint 不能直接用 std::max,因为模意义下比较大小没有自然语义。

  • BIT 支持 0-based 调用时,最好先把外部下标统一 normalize 到内部 1-based,再统一裁剪到 [1,n]

Hack 例子

初始叶子如果算错,会被这组打掉:

1
2
3
4
5
6
1
5
1 3
2 4
3 4
4 5

正确答案是 1,因为最大叶子一开始就是根 5

根转移如果只看最大邻居或最大根儿子,会被这组打掉:

1
2
3
4
5
6
7
1
6
1 4
2 6
3 5
4 5
5 6

正确答案是 2,对应集合 {3,6}{3,4,6}

1
2
3
4
5
6
7
8
6
/ \
2 5
/ \
3 4
/
1

因为 3,4 都可以转移(3 可以转移的原因在下面)

1
2
// * 只要能够压制其他子树的值(mx2),那么即可向 n 转移
// * 因为可以借刀杀人,借 n 的手,把自己子树中的其他值给干掉

AC 代码

AC 提交链接

本地代码已 AC;完整源码折叠在下面。

心路历程(WA,TLE,MLE……)

  • 一开始把转移看成 x -> y 的枚举,感觉红箭头很乱;后来固定终点 yy ,发现合法前驱是一段编号区间。

  • 中途误以为还需要扣掉 subtree(y),后来发现 need[y] < x 已经自动排除了这个情况。

  • 根节点是最容易绕的地方:普通点有父亲方向当退路,根没有,所以必须单独看根分支。

  • 真正让根变简单的是一句话:根转移只看第二大的根分支最大值。

  • 后面写代码时,几个 bug 都来自“把门槛误当成点”:secondMax 是阈值,不是要查的前驱状态。

附件

暂无。后续如果整理成完整 PDF 或动画,可以再补到这里。