splay 學習總結 QwQ

2021-10-09 12:46:04 字數 3721 閱讀 5637

省選之前就大概搞了下$splay$,然後因為時間不太夠就沒寫總結了,,,然後太久沒用之後現在一回想感覺跟沒學過一樣了嚶嚶嚶

所以寫個簡陋的總結,,,肥腸簡陋,只適合$gql$複習用,不建議學習用

然後先推薦兩篇部落格,,,

$orz\ yyb$的部落格$qwq$(我之前就是看這個學的$qwq$).

$orz\ xzy$學長的部落格$qwq$(這篇總結了支援的操作然後還提供了題單,解釋也挺詳細的,我真的好愛這種形式的題解$tt$)

$splay$是二叉搜尋樹的一種,和一般的平衡樹不同的是,它對樹高是麻油限制的

它基於乙個比較貪心的思想?就說查詢次數越多的節點離根節點應當是越近的.具體實現就,每次插入或操作乙個節點,就把它旋轉到根節點

然後$splay$的均攤複雜度大概是$o(log)$的

本來想在這兒寫下$splay$呲呲的各種功能,後來想了想,感覺還是寫了基操之後結合這些操作港應用會好些,,,所以功能這一帕就放後邊兒去了$qwq$

嗷還有就一般的學習博估計還會寫下什麼$splay$的旋轉原理昂,還有$splay$的結構體$code$什麼的,但因為這個是給$gql$複習用,就不寫這些了鴨$qwq$

包括後面的操作什麼的也是,因為是個複習向的玩意兒,所以只放**,原理什麼的只有我不太好$get$的才會寫下$w$?

定義

int rt,nod_cnt;

struct node}tr[n];

有時會根據題目性質加一些變數($eg$:$ad$標記,$reverse$標記等$qwq$),自己靈活變動即可

$umm$為了方便後文,先簡要介紹下這些變數的大致定義趴還是$qaq$

$rt$:根.$nod_cnt$:節點個數.

$ch[2]$:兩個子節點.$fa$:父親節點.$val$:這個點的值.$cnt$:這個值的數目.$sz$:這個點的子樹大小

$rotate$

il void pushup(ri x)

il void rotate(ri x)

$splay$

il void splay(ri x,ri goal)

if(!goal)rt=x;

}

$find$

void fd(ri x)

$insert$

il void insert(ri x)

nw=++nod_cnt;if(fa)tr[fa].ch[x>tr[fa].val]=nod_cnt;tr[nod_cnt].pre(x,fa);

splay(nw,0);

}

(乙個小$trick$,通常來說,為了防止邊界出現什麼問題之類的,會在初始的時候$insert$乙個$inf$和乙個$-inf$

查詢前驅後繼

int ask_pr(ri x)

查詢第$k$大

int ask_val(ri x)

else

if(x<=tr[tr[nw].ch[0]].sz)nw=tr[nw].ch[0];

else return tr[nw].val;}}

查詢排名

int ask_rk(ri x)

刪除

瞎寫下原理,,,?

考慮把$x$的前驅旋轉到根節點,然後把$x$的後繼旋轉到根節點的右兒子,由中序遍歷就可以知道,根節點的左兒子一定就只有$x$了,直接搞下就好$kk$

void delet(ri x)

tr[lst].ch[0]=0;

}

先港下,我這兒的應用全部指的對數列中的區間進行操作這樣兒,單點的全在前面昂$qwq$

昂然後如果是對某個數列進行操作,而且每次的操作是給定區間/單點座標然後要進行修改這樣兒,一般是考慮以下標作為節點值,,,?似乎是的趴$qwq$

還有就,我好像沒寫得特別全,,,再安利一次$xzy$學長的部落格,,,康完他的**其實就理解的差不多辣我$jio$得.真的寫的我覺得挺好的,總結也很全面,**十分詳盡,然後碼風我也很喜歡$qwq$,,,我真的好喜歡這篇部落格,,,好對我胃口昂$qaq$

提取區間

挺簡單的?對於$[l,r]$,考慮把$l-1$旋轉到根節點,把$r+1$旋轉到根節點的右兒子節點,由中序遍歷的性質不難得到$[l,r]$就是根節點的右兒子的左節點及其子樹

il void extract(ri x,ri y)

插入/刪除區間

見下區間交換$qwq$

區間加/翻轉

先把區間提取了,然後跟線段樹使得打個$ad$的$lazy\ tag$就好

il void reverse(ri x,ri y)

區間交換

先定義下區間交換,指交換兩個相鄰的區間昂$qwq$

總體思路就把後乙個區間放到乙個子樹上,插入到$l-1$和$l$之間就成

具體操作來說,先把$[l_,r_]$提取出來,然後把$[l_,r_]$記錄下來並刪了

然後再把$l_-1$挪到根,把$l_$挪到根的右子樹,把$[l_,r_]$插入到左子樹就歐克$qwq$

然後事實上這個就是插入刪除區間的合併版本遼,,,我就懶得再分開寫插入刪除區間了昂$qwq$

il void exchange(ri l1,ri r1,ri l2,ri r2)

區間迴圈移位

其實就是區間交換來著$hhh$

所以不港辣$qwq$

合併

這兒合併指的合併倆樹,,,

不會,找到了乙個學長的$code$,看不懂嚶嚶嚶,,,所以只放下存下,,,等$gql$以後變厲害了會來$upd$的!

il void merge(ri x,ri y)

{if(x==y)return;if(size[root[x]]>size[root[y]])swap(x,y);

f[x]=y;head=tail=0;dui[++tail]=root[x];int u;

while(head[x]基操板子

[x]區間翻轉板子

[x]寵物收養場

[x]鬱悶的出納員

[x]開車旅行

[ ]送花

[ ]永無鄉

[ ]書架

[ ]gamez遊戲排名系統

[ ]夢幻布丁

[ ]維護數列

[ ]排序機械臂

Splay演算法總結

splay是乙個功能強大的資料結構,可以實現一些平衡樹無法完成的操作 例題p3391 模板 文藝平衡樹 和平衡樹一樣,splay同樣也有左旋右旋的操作。並且splay中還有乙個核心操作,那就是將乙個節點移到另乙個節點下面,並保證整棵樹的中序遍歷不變。那麼很多操作就可以通過這兩個函式得出 比如在x後面...

splay 學習筆記

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

splay學習報告

省選將至,慌得一批,hale趕緊去學了學splay,防止被打爆,雖說一定會被打爆的 不過這玩意是真的噁心,hale花了三個中午去搞掉他 一點點自己的理解啦,嚶嚶嚶 emmm,廢話少說進入正題 一 啥是平衡樹?平衡樹,即平衡二叉樹 balanced binary tree 具有以下性質 它是一棵空樹或...