[學習筆記]笛卡爾樹


笛卡爾樹Cartesian Tree

前言

符合:祖先權值優先級更高,中序遍歷是序列本身

類比treap,只不過不平衡

 

既然不如treap平衡,支持操作就少了。

那么支持的操作,復雜度必須要更優了。

 

建樹

增量法

i=1~n

用單調棧維護最右邊路徑上的點

加入i點,從底向上找到第一個能放的位置,放上去,從棧中彈出的鏈就是左兒子。

中序遍歷性質顯然可以保證

權值優先級顯然可以保證

O(n)

(所以Treap也可以O(n)建樹)

 

例題:

求最大矩形

 

1.單調棧直接做。

2.建立小根堆笛卡爾樹,每個點的貢獻是:子樹sz*高度。正確性顯然

 

例題2:

 bzoj2616: SPOJ PERIODNI——笛卡爾樹+DP

 

例題3:

• 對於任意排列,定義其權值為:
• 首先求出排列的笛卡爾樹
• 對於樹上有兩個兒子的節點,設兒子的下標位置為 𝑎 和 𝑏
• 版本一:其對權值的貢獻為 |pa-pb|
• 版本二:其對權值的貢獻為 |𝑎 − 𝑏|
• 假設排列等概率隨機,求權值的期望
• 𝑛 ≤ 100

兩種不同的思路:

版本一:

 

關心兒子位置,

f[i][j]大小為i的樹,根節點在j位置權值

枚舉左兒子和右兒子的位置a,b,再分配編號:C(i-1,a)

可以把f[i][a]+a之類放在一起進行前綴和優化

純粹從計數考慮,還要維護方案數

 

個數從小到大擴展,位置合並並分配編號

還有相對設法

 

版本二:

權值絕對值要去掉,從小到大加入

大的樹就是放到葉子了

拼接的時候貢獻還要考慮父親權值不好處理

如果有些點必然會有葉子,那么放下一個權值之前,這些位置直接貢獻cnt的答案

類似放書那個題

f[i][j][k]放了前i個數,有j個位置還少兩個葉子,k個位置還少一個葉子(對未來承諾!)

 

合並

%%immortalCO

數據結構雜題集第三個有提到

定義關鍵點:一個樹最左邊和最右邊兩個鏈

關鍵點只有初始的O(n)個

合並x,y時候,對於x的右鏈和y的左鏈,從最底下開始往上找到第一個能放的位置,這一段長度設為len

之后這段關鍵點會被覆蓋住,不再存在。

然后y的這個點左兒子和x的這個點的右兒子進行類似fhq的合並,也就是一般的暴力合並

由於路徑上的點就是兩個段的關鍵點

關鍵點然后就消失了。

走的長度就是關鍵點減少的個數

所以均攤O(n)

從最底下開始找,可以用鏈表然后鏈表合並。單純記錄每個點最右邊的點也可以

sz什么的pushup就找到了。

(pushup這個不太好找到,最開始一段鏈很難搞。可以用LCT同時和笛卡爾樹合並做,用於打上標記)

挺trick的

 

感悟

具有“treap”的兩個性質

對於需要支持操作比較簡單的題目,尤其對於序列上有關大小的問題,笛卡爾樹的優秀結構可以使得處理有計可施

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM