學習筆記 splay入門(更新中)

2022-04-16 21:37:48 字數 1958 閱讀 1709

宣告:本部落格所有隨筆都參照了網路資料或其他部落格,僅為博主想加深理解而寫,如有疑問歡迎與博主討論✧。٩(ˊᗜˋ)و✧*。

終於學習了 spaly

\(splay\) !聽說了很久,因為dalao總是那這個開玩笑所以對它有深深的恐懼...但是學起來沒有那麼難啦,可能是因為提前學了替罪羊樹?(學替罪羊樹真的是痛苦555)

p3369 【模板】普通平衡樹

固定變數:

\(edge\) - 這個節點的值

\(tot\) - 這個節點重複的數

\(son[0/1]\) - 左兒子右兒子

\(fa\) - 節點的父親

\(size\) - 子樹的大小

struct ndoetree[n];
add(x)(新增乙個點):

1.找到特殊點

2.判斷 \(x\) 與特殊節點的值

\ \ 1)相等,則直接 \(++ \ tot\)

\ \ 2)不相等,則新建節點,更新變數

void add(int x)	

splay(u, 0);

}

del(x)(刪除乙個點):

1.找到 \(x\) 的前驅後繼

2.把前驅 \(splay\) 至根節點,把後繼 \(splay\) 成前驅的兒子

3.此時後繼的左兒子則為要刪除的點,判斷此節點的個數

\ \ 1)個數大於一則只用去掉乙個,然後 \(splay\)

\ \ 2)個數為一則直接刪掉

void del(int x)

splay(x, goal)(將 \(x\) 旋成 \(goal\) 的兒子):

1.判斷 \(x\) 是否是 \(goal\) 的兒子

\ \ 1)不是,則判斷 \(x\) 和它的父親、祖先是否在一條線上,進行不同的 \(splay\)

\ \ 2)是,判斷 \(x\) 是否是根並更新

void splay(int x, int goal)

if(! goal) root = x;

}

rotate(x)(單旋):

1.更新 \(x\) 和 \(z\) 的父子關係

2.更新 \(y\) 和 ( \(x\) 原來和 \(y\) 對應的那個兒子)的父子關係

3.更新 \(x\) 和 \(y\) 的父子關係

4.\(update \ x、y\)

void rotate(int x)

pre(x)(前驅):

1.將 \(x\) 變為樹根

2.有左子樹則進入左子樹,沒有則代表沒有比它小的數了

3.進入左子樹後一路往右子樹上湊(找最大的)

nxt(x)(後繼):

1.將 \(x\) 變為樹根

2.有右子樹則進入右子樹,沒有則代表沒有比它大的數了

3.進入右子樹後一路往左子樹上湊(找最小的)

int next(int x, int f)//我把pre和nxt寫到一起啦,實際上是一樣的

find(x)(輔助函式):

1.找到值等於 \(x\) 的那個節點

2.將節點旋轉至樹根

void find(int x)

query(x)(第k大的數):

1.先判斷整個樹的 \(size\) 是否大於等於 \(x\),若沒有則不存在

2.分三種情況繼續討論:

\ \ 1)左子樹 \(size\) 大於 \(x\) ,前往左子樹

\ \ 2)左子樹+這個節點的數的個數大於 \(x\),則直接返回這個節點的值

\ \ 3)更新 \(x\),前往右子樹

int query(int x)

}

splay 學習筆記

核心函式splay 每次訪問乙個節點,都把該節點轉到根 包括插入 查詢 操作 思想 對於訪問頻率較高的節點,使其處於根節點附近,從而保證log複雜度 splay可以維護中序遍歷是有序序列 也可維護 中序遍歷是當前操作後的序列 const int n 1e5 10 struct nodet n int...

Splay學習筆記

一種二叉樹的樹形資料結構,其定義如下 一種自平衡二叉搜尋樹,通過不斷將某個節點旋轉到根節點,使得整棵樹仍然滿足二叉查詢樹的性質,且保持平衡而不至於退化為鏈 root tot fa i child i 0 1 val i cnt i size i 根節點節點總數 父親左右兒子 點權出現次數 子樹大小 ...

Splay學習筆記

n n 500000 個數,要求維護區間加,區間查詢 很簡單,用線段樹 樹狀陣列隨便寫寫就能過 n n 500000 個數,維護插入 刪除 找區間第k大 小 用平衡樹 set也能過 n n 500000 個數,維護區間翻轉,區間查詢,插入,刪除 這個時候就需要用到伸展樹 splay splay是一種...