平衡樹學習小結

2021-08-15 18:36:52 字數 1239 閱讀 2745

最近系統的學習了學習平衡樹(splay),現做如下總結。

簡而言之,平衡樹是一種二叉樹。

何為平衡呢?平衡樹的「平衡」是由於他的深度較為平衡,一般穩定在log級別。

平衡樹因其「平衡」而保證了時間複雜度,減少了被卡的概率。

我們如何操作呢?

利用乙個性質:平衡樹因為中序遍歷是有序的,所以他的左子樹的所有元素都比他小,右子樹都比他大。

設旋轉的點為x,他的父親為y,父親的父親為z,son(a)表示a是他父親的左兒子還是右兒子。

此處分情況討論。y的左右兒子關係決定了x和z的大小關係。

因為我們要保證平衡樹的平衡,所以若y是z的右兒子,那麼x必定比z大,所以我們把x接在z的右兒子處,若y是z的左兒子反之。

繼續討論y與x的大小關係:顯而易見與「x與y的大小關係」相反,把y接在x後即可。

void rotate(int x)

這個操作是依靠rotate實現的。

分三種情況討論:

1.x和p是爺爺與兒子的關係,即只旋轉一次就可以到達位置:rotate(x)

2.son(x)和son(fa[x])不同:兩次rotate(x)

3.son(x)和son(fa[x])相同:rotate(fa[x]),rotate(x)

畫個圖就可以知道為什麼。

void splay(int x,int p)

if (!fa[x]) root=x;

}

利用二叉查詢樹的性質中序遍歷有序,我們每次比較當前節點和待查詢值的大小關係,決定下一步是往左子樹走還是往右子樹走。

int find_qq(int x)

int find_hj(int x)

找到x的前驅和後繼,將前驅旋轉到根(splay(qq,0)),後繼旋轉到根的右兒子(splay(hj,qq)),可以看出後繼的左兒子一定是空的,因為後繼的左兒子小於他並且大於前驅很明顯是不存在的。故將新元素插入到後繼的左兒子處。

void insert(int

x)

找到x的前驅,將其旋轉到根的位置,再找到x的後繼,旋轉到根的右兒子的位置,則根的右兒子的左兒子為需刪除的元素,清空根的右兒子的左指標即可。

void del(int

x)

查詢元素的前驅後繼,查詢元素排名,查詢排名為k的元素,插入/刪除元素等。

字尾平衡樹學習筆記

給定乙個空串s 操作1 代表在 s前加入乙個字母使之成為新s 操作2 代表在詢問在當前 s中有多少連續子串等於給定串t 假設我們已經有了串 s的字尾平衡樹 插入乙個字母c 我們用s i代表原串 s 從第 i個字元開始的字尾 則字尾 cs 與 任意乙個字尾 si 的大小關係可以用 c與s i 的第乙個...

回文樹學習小結

最近突然撿起了好久不搞的字串,研究了一下一直覺得很神奇的回文樹。相比於manacher,回文樹要顯得強大的多,同樣是接近o n 的複雜度,回文樹只需要多一點的空間,就可以實現許多用manacher實現起來非常複雜的功能。並且就 量而言,回文樹也足夠的簡短,作為處理回文串的工具,實在是非常的美妙。做了...

虛樹學習小結

其實虛樹這東西 不知道說什麼好 簡單易學呃 虛樹主要處理一種詢問總點數不超過o n 且每次詢問的那些點,在預處理之後,所求的值,只和他們,以及他們兩兩的lca有關 這裡有個顯然的結論,即m個點兩兩的lca不超過m 1個,將這m個點按dfs序排序之後相鄰兩點的m 1個lca就是這m個點兩兩的lca 建...