線段樹不支援的操作:刪除,插入
常見的平衡樹
treap 慢||好寫
sbt(大小平衡的樹) 非常快 比較好寫 ||功能不全
rbt 紅黑樹 特別快 || 非常難寫
以上操作支援插入刪除O(NlogN)
splay 特別慢。。≈O(sqrt(N))
不太好寫,功能強大
可持久化Treap
平衡樹一定是二叉樹
左兒子裡面的元素一定比他小
右兒子一定比當前節點大
中序遍歷一定排好序
每次遞迴的查詢
小——》左
大——》右
弊端:深度可能會非常深-->代價非常大
Treap=Tree+heap
treap:存兩個值[key,val]
val:每次插入的值,滿足平衡樹的性質
key:滿足堆的性質,直接rand,深度一定是logN級別的
merge(p1,p2):把以p1為根的Treap和以P2為根的Treap合併成一個Treap,p1的最大值應該<=P2的最小值
split(p,k):把以p為根的Treap拆成兩個Treap,一個有k個數,另一個有n-k個數,k為前k小
插入:先把樹分為x,y兩部分,然後把新的節點a看做是一棵樹,先與x合併,合併完之後將合併的整體與y合併
刪除:
merge實現
先找key最大的,比較p1,p2
- 若p1大
p1作為根,p2一定在p1的右邊,
p1.L=p1.L
p1.r=merge(p2,p1.r)
- 若p2
p2.r=p2.r
p2.L=merge(p2.L,p1)
merge返回的是根節點
split實現
size:子樹有多少個節點
當k<=p.L.size—>split(p.L,k)—>設p1為有用的子樹,那麼直接merge(p2,p.r)就好,把p2作為p的左孩子
當k==p.L.size+1 返回p.L+p,p.r
當k>p.L.size+1—>split(p.r,k-p.L.size-1)—>設p2為有用的子樹,直接merge(p,p1),把p1作為p的右孩子