由 ryz 講解
什麼是分治?
- 把一個較大規模的問題分成若干個較小規模的問題。
-
小規模的問題與原問題不同(根號分治)
-
小規模的問題與原問題相同(對數分治)
二分就是一種對數分治的方法。
操作序列分治
cdq 分治
修改和詢問的整體分治也被稱為 cdq 分治。
要求:修改對詢問具有可加性
主要操作:
-
將所有操作離線
-
對於區間 \([l,r]\),選取中點 \(mid\),只統計左修改對右的貢獻
-
遞迴 \([l, mid], [mid + 1, r]\)
無題號 函式
三種操作,加入一個一次函式,刪除一個函式,求 \(x_0\) 處所有函式的最大值,\(n\le 10^6\)。
第一眼看上去是線段樹分治(),但是要求用 cdq 做。
考慮維護一個下凸殼,插入好做,刪除不好做
考慮先從左往右掃一遍統計只有 + 的貢獻
然後從 \(r\rightarrow mid+1\),把刪除改成增加,倒著掃,從 \(r\rightarrow mid + 1\),用平衡樹維護下凸殼。
- 如何用平衡樹維護下凸殼
注意到斜率是單增的,考慮維護這個東西。
他肯定是包含了一個斜率區間,然後切掉了兩端直線的部分
那麼我們維護兩個東西:凸包上的斜率,交點的 \(x\) 座標
然後平衡樹找到斜率之後,直接向前向後列舉被刪除掉的斜率,維護這兩個東西就行
講了這麼久,最後告訴我 cdq 過不去()
正解是線段樹分治套平衡樹維護凸包(),這玩意兒是 \(O(n\log^2 n)\) 的
可以在節點時就把斜率排序好,再插入,用雙指標維護即可,複雜度 \(O(n\log n)\)
具體的,假設現在斜率為 \(a_1, \cdots a_n\), \(b_1, \cdots b_m\) 歸併排序一下就行