樹上資訊不好維護,可以先斷掉樹上的若干條邊,使得樹退化為若干條鏈,然後依次維護這些鏈。
對於一棵有根樹而言,可以選擇讓保留下來的若干條鏈上的點之間都是祖先關係,把斷掉的邊認為是虛邊,保留下來的邊認為是實邊,這樣我們得到的就是一棵樹的實鏈剖分(的一種方案),不難發現乙個點的所有孩子邊中最多只有一條實邊。
lct 的本質就是維護實鏈剖分,用 splay 來維護每條實鏈的資訊, splay 與 splay 之間通過虛邊聯絡起來,乙個 splay 的中序遍歷得到的是其對應實鏈按深度從淺到深排列得到的序列, splay 的根節點的父親節點表示的是這條實鏈中深度最淺的點的父親。( lct 的基本資訊)
把某個節點 \(x\) 旋轉到它所在的 splay 的根,那麼 \(x\) 的左兒子子樹表示的就是 \(x\) 所在實鏈中深度比 \(x\) 淺的節點,右兒子子樹表示的就是 \(x\) 所在實鏈中深度比 \(x\) 深的節點,此時可以發現, \(x\) 的實兒子虛兒子切換在 lct 中對應的就是切換 \(x\) 的右兒子子樹。( lct 虛實兒子/邊切換)
利用實兒子虛兒子切換的技巧,可以很簡單將乙個節點 \(x\) 換到和當且整棵樹的根同乙個 splay 中,並且與此同時還可以讓 \(x\) 成為 splay 中深度最深的節點,這時如果翻轉 \(x\) 和根所在的這個 splay ,就會讓 \(x\) 變成深度最淺的點,此時 \(x\) 就變成了整棵樹的根。( lct 換根操作)
利用 lct 虛實兒子切換及換根操作,可以將樹上任意一條路徑 \(u-v\) 提取出來並全部放到乙個 splay 中,此時就很好維護鏈上資訊了。( lct 維護鏈上資訊)
先僅考慮 lct 求子樹資訊,對於某個節點的子樹,子樹資訊可以分為兩部分,一部分是實兒子所在的子樹,另一部分是所有虛兒子所在的子樹,可以先維護一波所有虛兒子所在子樹的資訊,然後利用 splay 將這條實鏈中所有虛子樹的資訊合併得到整棵子樹的資訊。( lct 子樹查詢)
再考慮 lct 修改子樹資訊,和上面差不多,關鍵是下傳標記,乙個點下傳標記的時候並不能直接列舉它的所有虛兒子,否則時間複雜度就假掉了,可以再用乙個 splay 來給所有虛兒子打標記,這樣讓下傳標記的複雜度正確。( lct 子樹修改)
如果乙個 dp 方程可以表示為矩陣相乘的形式,那麼這個 dp 方程就可以用 splay 去維護,於是乎就可以用 lct 去維護乙個樹上面的 dp 方程,也就是用 lct 維護動態 dp ,這和 lct 子樹查詢本質是一樣的。( lct 維護動態 dp )
有的時候我們並不需要實現 lct 裡面的大部分操作(換根、 link 、 cut 等),只需要鏈上查詢和鏈上修改,那麼此時我們就可以將 lct 靜態下來( splay 不需要旋轉,所以我們可以一開始就找到 splay 最平衡的位置),具體實現方法就是用輕重鏈剖分的方法去虛實鏈剖分,然後對於每條實鏈,將每個點的點權認為是它所有虛兒子子樹和,然後找帶權重心一路遞迴下去得到這條實鏈的 splay ,這樣得到的 lct 滿足每個點向上跳的次數是 \(\log_2n\) 級別的,因為虛邊是 \(\log_2n\) 級別的,而每次跳實邊(跳 splay 上面的父親節點)包括的節點數量都會乘以 \(2\) ,所以每個點向上跳的次數是 \(\log_2n\) 級別的。
經過了靜態化 lct 的操作之後,維護鏈上資訊和普通 lct 的方法就有所不同了,此時如果將 splay 類似成為線段樹的話那麼維護鏈上資訊的方法就和輕重鏈剖分維護的方法差不多,子樹資訊查詢和普通 lct 類似,子樹資訊修改此時每個點的虛兒子維護的 splay 也讓其靜態化,其它都是一樣的。
lct 維護邊資訊可以將邊轉化成點,然後按維護點資訊的方法去維護,也有另一種方法,就是將邊資訊下放到點資訊上面去然後再維護。
對於某乙個點 \(x\) ,它左兒子 \(l\) 維護 \(x\) 與 \(l\) 子樹代表的點形成的鏈之間的邊的資訊,它右兒子 \(r\) 維護 \(x\) 與 \(r\) 子樹代表的點形成的鏈之間的邊的資訊,這樣的話於普通 lct 而言幾乎唯一需要更改的就是 rotate 操作了,分當且 rotate 的節點是否有另一邊的兒子討論即可。
這種做法的好處就是不需要為邊重新開點了,降低了常數並減小了點和邊不同處理的分類討論。
關於樹論 動態樹問題(LCT)
搬運 看一道caioj1439 題目描述 一開始給你一棵n個點n 1條邊的樹,每個點有乙個權值wi。三種操作 op 1 u v 在點u和點v之間建一條邊。op 2 u v 摧毀點u到點v之間的邊。op 3 w u v 將點u和點v之間路徑上的點 包括u,v 權值增加w。op 4 u v 詢問點u到點...
關於學習和複習
經常有學員問我 學習一兩個月以後,就把最開始學習的東西忘記了,然後就要複習。但是每天都要學習新東西,那麼晚上自習時就不知道該看當天學習的內容,還是看以前學習的內容。經常覺得在瞎忙活,什麼都沒有弄明白,不知道從 下手。我分析 一般這樣的學員就是以前的基礎沒有打好,那麼就應該從基礎開始複習。複習非常重要...
基礎複習 關於事務
又有幾天沒來了,用了十多個小時幫人做個簡易的招聘 主要收穫是在實際在專案中應用了內外鍵,內外聯查詢,熟練地css布局,不過缺點在於並沒有摒棄table元素,要努力訓練div代替table的使用。其次是母版頁的更熟練的應用。總結一下最近收穫的知識點 1,檢視中存的是select語句而不是結果集資料 盡...