[學習筆記]線段樹騷操作選講
阿新 • • 發佈:2018-12-08
引入
- 眾所周知,線段樹可以維護序列,進行區間操作
- 單點加 + 區間求和
- 區間加 + 區間求和
- 區間加 + 區間乘 + 區間求和
- (省略 行)
- 但有些操作不能像上面三個問題一樣通過簡單的打標記 + 提取區間解決
- 而需要用到一些 trick
一、勢能線段樹
- 我們知道,線段樹能夠通過打標記實現區間修改的條件有兩個:
- (1)能夠快速處理標記對區間詢問結果的影響
- (2)能夠快速實現標記的合併
- 但有的區間修改不滿足上面兩個條件
- 但某些修改存在一些奇妙的性質,使得序列每個元素被修改的次數有一個上限
- 可以線上段樹每個節點上記錄一個值,表示對應區間內是否每個元素都達到修改次數上限
- 區間修改時暴力遞迴到葉子節點,如果途中遇到一個節點,這個節點的對應區間內每個元素都達到修改次數上限則在這個節點 return 掉
- 可以證明覆雜度為
- 用幾個簡單的栗子說明一下
一、區間開平方,區間求和
- 一個數 被開平方 後會變成 或 ,繼續開根後不變
- 所以線段樹節點上用一個變數記錄是否區間內全為 或
- 修改時遞迴到葉子,如果到達了區間內全為 或 的節點則 return 掉
- 複雜度
二、區間取模,區間求和
- 一個數 對 取模,如果 則 至少變小一半
- 每個節點維護區間和以及區間最小值
- 區間對 取模時仍然遞迴到葉子
- 如果某節點的區間最小值小於 則 return 掉
- 複雜度
三、區間除(下取整),區間加,區間求和
- 區間整除 是無效的,直接跳過
- 否則整除一個數會使區間內最大值與最小值的差至少減小一半
- 維護區間最小值和最大值以及區間和,區間加標記
- 整除時遞迴到葉子
- 如果最小值和最大值的差為 ,則該區間內所有數都相等
- 直接打上標記,注意這時候標記可以處理對區間和的影響
- 複雜度
二、李超樹 / 李超線段樹 / 超哥線段樹
- 考慮經典問題
- 維護一個二維平面
- 支援橫座標 範圍內插入一條線段,查詢某個橫座標上的最高點
- 換成人話,區間對一個等差數列取 ,單點查值
- 線段樹每個節點維護一個標記(一條線段)
- 仍然把 拆成線段樹上不超過 個區間
- 我們要處理的關鍵問題是標記的合併,也就是兩條線段 , 放在一起的情況
- 如果在當前節點對應區間
內
完全在
之上,則該區間打上標記線段
- 如果
完全在
之上同理
- 最重要的情況:
和
在橫座標
的左邊,
的右邊位置相交,在
的右半段
在
之上
- 這時候將 保留在當前節點上, 的前半段下傳到左子節點
- 注意這時候 的前半段可能會和左子節點快取的線段相交
- 所以這時候需要往左子節點遞迴
- 還有 種情況和上面差不多
- 往交點所在的子節點遞迴,另一半區間內在上方的線段保留,在下方的線段下傳
- 複雜度
三、線段樹維護單調子序列
- 考慮經典問題
- 給定一個序列,支援單點修改
- 詢問給出
- 求有多少個 滿足 或者 內任何一個數都不大於第 個數
- 換句話說,求 內有多少個位置 是 內對應的以 為結尾的字首最大值
- 定義函式
- 表示線段樹 節點對應區間內,有多少個數不小於 且是對應區間的字首最大值
- 線段樹上維護區間最大值
- 如果 對應的區間最大值小於 則
- 設 的左右子樹分別為 和
- 如果 的最大值小於 則