LCT 學習筆記

2022-09-07 02:54:11 字數 1642 閱讀 3936

可能叫動態鏈剖分會比較合適?

回顧重鏈剖分,我們將 x 所有兒子中子樹 siz 最大的那個兒子欽定為重兒子,乙個結點與它的重兒子的連邊稱為重邊,其餘稱為輕邊。重邊和輕邊形成的鏈把整棵樹剖分成了若干個 dfs 序上的連續段,這樣我們就能使用諸如線段樹等靜態資料結構維護鏈上的資訊了。

重剖的侷限性在於它所維護的樹的形態必須是靜態的,在面對一些需要動態更新原樹形態的問題難免乏力。於是就有了 lct(動態樹),它支援:維護乙個森林,更換某棵樹的根(makeroot),新建邊(link),刪除邊(cut),修改及查詢鏈上的資訊等操作。

把邊分為實邊和虛邊,每個結點最多有乙個實兒子(可以沒有實兒子)。實邊連成的鏈稱為實鏈,改為以每個結點的深度為關鍵戳用 splay 維護實鏈上的資訊,這樣更加靈活。實鏈與實鏈之間通過虛邊相連,這裡採用「認父不認子」的處理方法把實鏈對應的 splay 連線起來。即:將每棵 splay 的 root 的父親結點設為它所維護實鏈的鏈頂在原樹意義上的父親 \(x\),但是並不更改 \(x\) 在 splay 裡的左兒子和右兒子。這樣的好處在於:既保留了 splay 本身的功能性,又能從某個結點出發還原出它到根結點的路徑,從而還原原樹結構。同時,splay 可以方便地提取/分離子樹,這又使得我們能夠方便地切換虛實邊,從而斷掉一條實鏈,以及自底向上連線若干條實鏈。這些優勢將在 access 操作裡體現。

access 操作是 lct 的核心操作,它的效果是把 \(x\) 在原樹意義上到根結點的路徑中的所有邊都變為實邊,相應地,不在路徑上且連線了路徑上結點的所有實邊要變成虛邊。它的流程是:先新建乙個空結點 \(y\),把 \(x\) splay 到根結點,將其右兒子改為 \(y\)(\(x\) 成為根結點後所有深度大於 \(x\) 的結點便都集中在了 \(x\) 的右子樹里,更改右兒子相當於把 \(x\) 與其實兒子之間的實邊切換為虛邊,也就是斷掉了 \(x\) 所在實鏈中更靠下的部分,並把 \(y\) 對應的實鏈結了上去 );然後令 \(y=x,x=fa_x\)(這裡相當於跳到更上面的實鏈,繼續把之前拼成的實鏈與上面的鏈拼接),重複第一步直到走到原樹意義上的根結點。**如下:

void access(int x)

splay(t);

}

在 access 操作的基礎上,考慮把某棵樹的根變為 \(x\) 會發生什麼。設原樹根為 \(r\),換根只會使原樹上 \(x\) 到 \(r\) 的簡單路徑上的點的深度序列翻轉。由於 splay 是以深度為關鍵戳維護的,所以只需要先 access(x),然後把 \(x\) 所在 splay 整體翻轉。這個也是經典操作,只需要額外維護乙個懶標記。

void makeroot(int x)
先把 \(x\) 所在樹的根換成 \(x\),然後連一條 \(x\to y\) 的虛邊。

int findroot(int x)

void link(int x,int y)

先判掉 \(x,y\) 沒有直接連邊的情況。

然後把 \(x,y\) 放在同一棵 splay 裡並讓它們相鄰,這個可以通過 makeroot 和 splay 操作實現

void cut(int x,int y)
其餘操作大概都是修改和維護鏈上資訊,可以參考 splay 的各種操作,一般來講 splay 能維護的 lct 也能維護,如 [國家集訓隊]tree ii。

LCT 學習筆記

自己定的學習計畫看起來完不成了 兩天沒學東西,全在補題 決定趕快學點東西 於是就學lct了 link cut tree是一種資料結構,我們用它解決動態樹問題 但是lct不叫動態樹,動態樹是指一類問題 那麼lct的中文名是啥啊 這是 個和 splay 樣只需要寫幾 yi 個 dui 核心函式就能實現一...

動態樹(LCT)學習筆記

candy flashhu xzyxzy 想要學lct的還是看這幾篇比較好。我這篇只是總結一些容易理解錯的或者一不小心打錯的地方。lct link cut tree 就是又可以link 動態加邊 又可以cut 動態刪邊 的維護一片森林的資料結構。lct使用實鏈剖分,對每一條實鏈用splay維護 一棵...

LCT入門筆記

lct是動態樹的一種,通過維護實鏈和虛鏈來維護所有路徑之間的關係 類似於樹鏈剖分 這樣做的目的是為了減少某些鏈上的修改 查詢等操作的複雜度。雖然lct常數巨大。學lct的大部分都會樹剖吧?我們都知道樹剖維護子樹最大的兒子並形成一條重鏈,由於樹剖是靜態的,所以可以用線段樹來維護。而由於lct需要維護動...