動態樹Link cut tree LCT 總結

2022-05-08 17:39:09 字數 1945 閱讀 1443

動態樹是個好玩的東西

lct題集

splay

樹鏈剖分(好像關係並不大)

先搬dalao部落格

講了這麼多,其實就是維護森林的樹鏈剖分,每一條鏈用splay維護

每乙個splay維護的是一條從上到下按在原樹中深度嚴格遞增的路徑,且中序遍歷splay得到的每個點的深度序列嚴格遞增。

比如有一棵樹,根節點為1(深度1),有兩個兒子2,3(深度2),那麼splay有3種構成方式:,,

,,(每個集合表示乙個splay)

而不能把1,2,3同放在乙個splay中(存在深度相同的點)

每個節點包含且僅包含於乙個splay中

邊分為實邊和虛邊,實邊包含在splay中,而虛邊總是由一棵splay指向另乙個節點(指向該splay中中序遍歷最靠前的點在原樹中的父親)。

因為性質2,當某點在原樹中有多個兒子時,只能向其中乙個兒子拉一條實鏈(只認乙個兒子),而其它兒子是不能在這個splay中的。

那麼為了保持樹的形狀,我們要讓到其它兒子的邊變為虛邊,由對應兒子所屬的splay的根節點的父親指向該點,而從該點並不能直接訪問該兒子(認父不認子)。

打通\(x\)到動態樹的根的路徑(使路徑上的所有點在同乙個splay中)

void access(int x)
使\(x\)變成動態樹的根

void makeroot(int x)
用來判斷連通性(類似並查集)(findroot(x)==findroot(y)表明x,y在同一棵樹中)

inline int findroot(int x)
打通\(x\)到\(y\)的路徑(類似access)

void split(int x, int y)
連線\(x-y\)

void link(int x, int y)
斷開\(x-y\)

void cut(int x, int y)
洛谷p3690 【模板】link cut tree (動態樹)

code

#include#define ll long long

#define rg register

const int n = 300010;

using namespace std;

inline int gi()

struct node t[n];

int s[n], top;

void putrev(int x)

#define pushup(x) (t[x].s = (t[x].v^t[t[x].ch[0]].s^t[t[x].ch[1]].s))

void pushdown(int x)

return ;

}#define get(x) (t[t[x].fa].ch[1]==x)

bool isroot(int x)

void rotate(int x)

void splay(int x)

pushup(x);

return ;

}void access(int x)

void makeroot(int x)

inline int findroot(int x)

void link(int x, int y)

void split(int x, int y)

void cut(int x, int y)

int main()

else if (op == 1) link(x, y);

else if (op == 2) cut(x, y);

else

} return 0;

}

動態樹問題

當一類題目中的樹需要支援換根 加邊 刪邊的這些操作時,會改變樹的形態,並要求維護一些資訊,這類問題稱為動態樹問題。這裡有我寫的學習小記 link cut tree學習小記 支援的功能 換根,加邊,刪邊,鏈上資訊維護。不支援的功能 子樹資訊維護。習題 彈飛綿羊,魔法森林,substring。我不知道真...

動態樹分治

不得不說,樹結構真是巧妙神奇。因為結構簡單,所以變形剖多,在競賽中玩出的花樣也最多。動態樹分治,顧名思義,解決待修改的樹分治問題。原本的樹分治基於邊或者重心的分治可以解決大多數靜態樹鏈問題,但是待修改怎麼辦?其實很簡單,因為樹結構是不變的,就是樹分治的基礎結構不變,對於修改和詢問,只需要在第一次樹分...

動態樹雜談

動態樹,一類用來維護森林連通性的資料結構,主要使用splay來維護偏愛點 邊 preferred child edge 並且通過點在不同splay中的移動提取路徑,或者是修改父子關係以連線或斷開樹邊 動態樹由於其需要動態的修改點 邊關係,所以需要動態的維護點 邊,從而選擇偏愛點 邊而不是像樹鏈剖分中...