博客觀賞效果更佳:
github
cnblogs
算法講解
這個算法用於解決三維偏序問題。
三維偏序:給定 n n n 個三元組: ( a i , b i , c i ) (a_i,b_i,c_i) ( a i , b i , c i ) ,求同時滿足滿足 a i ≤ a j , b i ≤ b j , c i ≤ c j a_i\le a_j,b_i\le b_j,c_i\le c_j a i ≤ a j , b i ≤ b j , c i ≤ c j 的 ( i , j ) (i,j) ( i , j ) 的數量。
那這該咋求呢⊙(・◇・)?
先把維度降下來,二維偏序,會不會做?就是求多少個 ( i , j ) (i,j) ( i , j ) 滿足 a i ≤ a j , b i ≤ b j a_i\le a_j,b_i\le b_j a i ≤ a j , b i ≤ b j 。
顯然,先按照 a a a 排一下序。然後就變成了 i < j , b i ≤ b j i<j,b_i\le b_j i < j , b i ≤ b j 的問題了。可以用樹狀數組做。最典型的案例就是逆序對問題,這個都寫熟練了哈(*╹▽╹*)
三維偏序的問題,也是先按 a a a 排一下序。然後接下來的問題考慮分治(這樣的分治過程被我們稱爲“cdq分治”)
假設我們要求 [ l , r ] [l,r] [ l , r ] 中的答案。已經求好了 [ l , m i d ] , [ m i d + 1 , r ] [l,mid],[mid+1,r] [ l , m i d ] , [ m i d + 1 , r ] 中的答案,現在只需要考慮跨區的答案了。
那麼我們可以把 [ l , m i d ] [l,mid] [ l , m i d ] 和 [ m i d + 1 , r ] [mid+1,r] [ m i d + 1 , r ] 內部都按照 b b b 排序。因爲我們只要考慮跨區的答案,那麼我們把兩邊分別都隨便排序,對跨區的時候 a a a 的大小關係沒有影響。然後我們在 [ m i d + 1 , r ] [mid+1,r] [ m i d + 1 , r ] 中枚舉一個元素 j j j ,找到在 [ l , m i d ] [l,mid] [ l , m i d ] 中有多少個 i i i 滿足 b i ≤ b j b_i\le b_j b i ≤ b j ,然後這個 i i i 顯然是遞增的。然後我們一邊單調的維護這個 i i i ,一邊用樹狀數組維護 c i ≤ c j c_i\le c_j c i ≤ c j 的數量即可。
板子
洛谷3810 陌上花開
(↑代碼找我老婆要)(那張圖是一個鏈接(*▽ *))(偷偷測試功能)