n(n<=500000)個數,要求維護區間加,區間查詢
很簡單,用線段樹/樹狀陣列隨便寫寫就能過
n(n<=500000)個數,維護插入、刪除、找區間第k大/小
用平衡樹/set也能過
n(n<=500000)個數,維護區間翻轉,區間查詢,插入,刪除
這個時候就需要用到伸展樹(splay)
splay是一種極(常)靈(數)活(大)的資料結構,它能夠維護線段樹的部分操作和平衡樹的操作
它的美妙之處在於能夠旋轉,從而完成一系列操作
它的旋轉和平衡樹的只轉一次不同,它可以進行雙旋操作來保證較優秀的時間複雜度(但常數還是大)
雙旋操作是基於單旋的
首先是單旋:
和平衡樹相同
然後是雙旋:
當p不是根節點,且x和p同為左孩子或右孩子時進行zig-zig操作。
當x和p同為左孩子時,依次將p和x右旋;
當x和p同為右孩子時,依次將p和x左旋。
當p不是根節點,且x和p不同為左孩子或右孩子時,進行zig-zag操作。
當p為左孩子,x為右孩子時,將x左旋後再右旋。
當p為右孩子,x為左孩子時,將x右旋後再左旋。
有了單旋和雙旋就可以進行splay操作:
int get(int o)
void rotate(qaq o)
void splay(int o,int goal)
if(!goal) rot=o;//換根
push_up(o);
}
進行區間操作[l,r]時,常常把節點l-1轉到根,r+1轉到根的右兒子,這樣根的右兒子的左兒子就是操作區間 ,並且常常新增虛擬節點0和n+1來進行[1,n]的操作
區間翻轉就直接交換左右兒子
區間加直接加lazy標記
還能查詢某乙個值的排名:找到節點,轉到根,根的做兒子大小+1就是排名
注意:splay中有些操作不能同時進行,例如求第k大和區間操作就不能同時進行,因為前一種操作改變了原序列順序,後乙個操作要求不能改變,這樣就發生衝突。splay旋轉僅僅是改變樹的形狀,並沒有改變原序列順序(樹的中序遍歷)
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入門(更新中)
宣告 本部落格所有隨筆都參照了網路資料或其他部落格,僅為博主想加深理解而寫,如有疑問歡迎與博主討論 終於學習了 spaly splay 聽說了很久,因為dalao總是那這個開玩笑所以對它有深深的恐懼.但是學起來沒有那麼難啦,可能是因為提前學了替罪羊樹?學替罪羊樹真的是痛苦555 p3369 模板 普...