[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)\)

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