線段樹套平衡樹
常見用途
在算法競賽中,我們有時需要維護多維度信息。在這種時候,我們經常需要樹套樹來記錄信息。當需要維護前驅,後繼,第 \(k\) 大,某個數的排名,或者插入刪除的時候,我們通常需要使用平衡樹來滿足我們的需求,即線段樹套平衡樹。
過程
我們以 二逼平衡樹 為例,來解釋實現原理。
關於樹套樹的構建,我們對於外層線段樹正常建樹,對於線段樹上的某一個節點,建立一棵平衡樹,包含該節點所覆蓋的序列。具體操作時我們可以將序列元素一個個插入,每經過一個線段樹節點,就將該元素加入到該節點的平衡樹中。
操作一,求某區間中某值的排名:我們對於外層線段樹正常操作,對於在某區間中的節點的平衡樹,我們返回平衡樹中比該值小的元素個數,合併區間時,我們將小的元素個數求和即可。最後將返回值 \(+1\),即為某值在某區間中的排名。
操作二,求某區間中排名為 \(k\) 的值:我們可以採用二分策略。因為一個元素可能存在多個,其排名為一區間,且有些元素原序列不存在。所以我們採取和操作一類似的思路,我們用小於該值的元素個數作為參考進行二分,即可得解。
操作三,將某個數替換為另外一個數:我們只要在所有包含某數的平衡樹中刪除某數,然後再插入另外一個數即可。外層依舊正常線段樹操作。
操作四,求某區間中某值的前驅:我們對於外層線段樹正常操作,對於在某區間中的節點的平衡樹,我們返回某值在該平衡樹中的前驅,線段樹的區間結果合併時,我們取最大值即可。
性質
空間複雜度
我們每個元素加入 \(O(\log n)\) 個平衡樹,所以空間複雜度為 \(O((n + q)\log{n})\)。
時間複雜度
- 對於 1,3,4 操作,我們考慮我們在外層線段樹上進行 \(O(\log{n})\) 次操作,每次操作會在一個內層平衡樹樹上進行 \(O(\log{n})\) 次操作,所以時間複雜度為 \(O(\log^2{n})\)。
- 對於 2 操作,多一個二分過程,為 \(O(\log^3{n})\)。
經典例題
二逼平衡樹 外層線段樹,內層平衡樹。
實現
平衡樹部分代碼請參考 Splay 等其他條目。
操作一:
1 2 3 4 5 6 7 8 9 10 11 | |
操作二:
1 2 3 4 5 6 7 8 9 | |
操作三:
1 2 3 4 5 6 7 8 9 | |
操作四:
1 2 3 4 5 6 7 8 | |
相關算法
面對多維度信息的題目時,如果題目沒有要求強制在線,我們還可以考慮 CDQ 分治,或者 整體二分 等分治算法,來避免使用高級數據結構,減少代碼實現難度。
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:Dev-jqe, HeRaNO, huaruoji
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用