[NOI2020]超现实树

超现实树(Surreal)

时隔 10 个月,我又来复盘此题啦 /se

当时蒟蒻不会这道题,胡了个三树合并的做法,以为 GG 但发现竟然还有 40 pts /jy

什么是三棵树合并?一个简单的例子:

这是第 2 组样例。它的答案为 Almost Complete。对于更复杂的树,如果其它部分完全一样,三棵树分别是如上的结构,那么可以合并到一块,例如

如果能合并成像右边一样是一个只包含根节点的树,它就是 Almost Complete,否则就是 No

于是你开始信心满满地开始 rush 一份线性的带 Hash 的代码,当你开始一组组地跑样例时,发现 Case 5 WA 了!

如果出题人按照开始只下发前 4 组样例,估计大多数错解选手就会跑路看 T1 或 T3,还好他是 Almost 良心 的(bushi),补发了两组!

此时要反思为什么上面是错的。在第一幅图中:

\({\rm grow}(\)\()+{\rm grow}(\)\()+{\rm grow}(\)\()={\rm grow}(\)\()\setminus\{\)\(\}\ne{\rm grow}(\)\()\)

发现两者不完全等价!我们尝试修正该方法。我们使用红色的节点来 特殊化 被合并的节点,也就是像这样

按照这样,我们重新合并图二中的树

但是接下来又要纠结了:带有特殊节点的合并是什么样的?我们不难遐想到有如下多种可能

合并的组合突然间多了很多。我们试图来讨论。但在讨论前,我们想要弄明白 特殊节点 的含义,就目前来看,它表示:除了特殊节点自身一个节点的树无法生成,其它任意子树皆可被生成

首先,我们要排除上图中的 (1,4)(最右上角的),这种情况不具有意义。它表明:左右子树同时不能为自身。而在这样的限制条件下,无法产生的树的集合大小为 无限大(令左儿子为自身,右儿子形态任意),即使加强限制使得集合大小有限,该限制 不强于 其它七种情况,换句话说它是 没有用的。想避免此种情况,也就是说红色节点的个数必须 \(\le 1\)

接着,我们来一一讨论。对于对称的情况我们可以转化,有用的情形总结如下:

\({\rm grow}(\)\()+{\rm grow}(\)\()+{\rm grow}(\)\()={\rm grow}(\)\()\setminus\{\)\(~+~\)\(\}\)

\({\rm grow}(\)\()+{\rm grow}(\)\()+{\rm grow}(\)\()={\rm grow}(\)\()\setminus\{\)\(~+~\)\(~+~\)\(\}\)

\({\rm grow}(\)\()+{\rm grow}(\)\()+{\rm grow}(\)\()={\rm grow}(\)\()\setminus\{\)\(~+~\)\(~+~\)\(\}\)

\({\rm grow}(\)\()+{\rm grow}(\)\()+{\rm grow}(\)\()={\rm grow}(\)\()\setminus\{\)\(~+~\)\(~+~\)\(\}\)

\({\rm grow}(\)\()+{\rm grow}(\)\()+{\rm grow}(\)\()={\rm grow}(\)\()\setminus\{\)\(~+~\)\(~+~\)\(~+~\)\(\}\)

三角形表示该点构成的子树形态任意。

发现第 3 种和第 5 种情况下,不可生成的部分中有一种情况,它可以拓展出无数种树。这也直接指出三棵树合并的错误之处了。这时发现第 5 组中:

\(\{\)\(\}+{\rm grow}(\)\()={\rm grow}(\)\()\setminus\{\)\(\}\)

利用右边的红点,可以把右边的子树“封死”,而且不难证明该条件是必要的。这样不可生成的集合大小就是有限的了!

于是能推导出四棵树合并:

\({\rm grow}(\)\()+{\rm grow}(\)\()+{\rm grow}(\)\(\}+{\rm grow}(\)\()={\rm grow}(\)\()\setminus\{\)\(~+~\)\(~+~\)\(~+~\)\(\}\)

可是右边的东西还是有点复杂?不过发现:等式右边都满足,由根生长的树,却不能在等式左边生长出来的数目是 有限的。如果拓宽 特殊点 的定义:特殊点所在的子树内对于数量 有限 的拓展下无法生成,除此之外其它基于原树拓展的部分均可生成。

不难发现上述合并法则依然成立!

为了统一,我们甚至可以

这样就可以将四棵树合并的策略适用于任何情况了。注意初始情况下 特殊节点 不可生成的树为空,但只要合并过,就一定非空,可以证明这样转换不会出现超出该合并法则的情况。

于是修正最开始三棵树合并的代码,使用 Hash 跑四棵树合并,即可通过本题。期望复杂度 \(\mathcal O(n)\)

这道题还要用 Hash?Too weak!这里还有没挖掘的性质,可以大幅降低代码实现难度。

对于第二幅图中的树,它对答案是不起作用的,因为若干次合并后会出现这样的情况:

这与前面的推论矛盾了。什么样子的树在合并的过程中不会出现这样的情况?稍加思考可以发现,沿着主链合并的点一定是红点,所以另一个方向上 不能出现合并。该种类树的形态:有一条主链,然后链上的每一个非叶子节点要么没有另一个孩子,要么有。

这跟官方题解中 树枝 的定义一致。

于是删掉无用的树之后,我们可以递归合并。这样就大幅简化代码了。复杂度仍然可以做到 \(\mathcal O(n)\)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章