現在只有口胡. 別急.
這些算法口胡起來很舒服啊. 但是沾點離線的一般都不太好寫/ng
Stop learning useless algorithms. Go and solve some problems, using binary search.
1. cdq 分治
大致思路是, 讓修改在查詢之前, 成爲一個靜態問題.
我們直接把一個操作序列分成兩半, 一次算完前面的修改對後面查詢的貢獻, 然後分治下去. (類似於歸併排序)
這個操作要求可以先算一些修改的貢獻, 再算另一些修改的貢獻.
例 1: 樹狀數組板子, 單點加, 區間求和.
首先簡單轉化變成單點加 (初始值也視爲該操作), 前綴求和.
2. 整體二分
每個詢問二分一遍太慢了.
所以我們考慮直接一起二分掉, 換句話說我們共用了判定的 mid.
每次判定完之後, 按照結果將詢問劃分到兩邊, 繼續二分下去.
例 1: 區間第 k 小.
例 2: Dynamic Rankings.
3. 線段樹分治
最先學會的一個 (?
用處在於, 把刪除操作轉成撤銷操作, 而後者是容易的.
方法是, 我們處理出來每個元素存在的時間段 (從插入到刪除).
然後對着時間開線段樹, 這樣貢獻就變成了線段的形式, 直接扔到線段樹上拆成 \(O(\log n)\) 段.
然後對着線段樹 dfs 一遍就完事了, 此時只有加入和撤銷.
例 1: 離線動態圖連通性.
處理出來每條邊存在的時間段, 插到線段樹裏, dfs 的時候用可撤銷並查集即能維護在某一時刻的連通性.
例 2: P4585 [FJOI2015]火星商店問題
(咕咕咕)
4. 貓樹分治/二區間合併
喵喵喵.
貓樹的精神在於預處理從中間往兩邊的貢獻, 然後直接合起來.
所以這個東西也可以拿來分治, 每次處理經過中點的所有區間, 剩下的下放到兩邊.
(實際上就是對鏈上做點分治)
例: CF1100F Ivan and Burgers
我們不考慮前綴線性基那種離譜東西. 假設我們只會合併線性基.
使用上面的方法我們可以輕鬆解決該問題. 每次預處理出來中點向左的後綴構成的線性基和中點向右的前綴構成的線性基, 對於經過中點的查詢, 直接合並即可.
然後把剩下的詢問分到兩邊, 總時間複雜度差不多是 \(O(q\log^2n)\).