luogu随机到了一道题,看了题解才知道是CDQ。。
三维偏序
求满足
$ i<j,ai<aj,bi<bj $
的 (i,j) 对数。
用 solve(l,r) 表示求解区间 [l,r] 。把区间折半,可以递归求解 solve(l,mid) 和 solve(mid+1,r) 。现在关心
$ l≤i≤mid,mid+1≤j≤r $
的求解。
将 [l,mid] 和 [mid+1,r] 分别按照 a 排序,利用双指针,对于每一个 j≤[mid+1,r] 将所有 ai<aj 的 i 加入树状数组。加入树状数组时,在 bi 位置 +1 (可能要离散化)。对于每个 j ,询问树状数组 ≤bj 位置的和求和即可。
复杂度 O(nlog2n) 。
dp转移
考虑dp转移
$ dpi=1+maxj=1i−1dpj[aj<ai][bj<bi] $
其实就是二维的最长上升子序列。
用树状数组维护最大值,其他差不多,但是注意 l≤i≤mid,mid+1≤j≤r 的求解要在 solve(l,mid) 和 solve(mid+1,r) 之间进行,因为如果先执行 solve(mid+1,r) ,此时 mid+1 wei位置还没有通过 mid 之前位置来转移,不是正确的dp值,不能用来更新 mid+1 位置以后的位置,而使用“中序遍历”则可以解决这个问题。
luogu 4093
将一个位置能达到的最小值(包括原始数 a )记为 mn , 最大值(包括原始数 a )记为 mx ,不难发现转移是 mxi≤aj 且 ai≤mnj 。
左右两边分别按照 mx 和 a 升序。
upd: 原代码 存在一些重大bug:每次solve暴力memset树状数组清空,竟然跑出了860ms。。。
时间序列
将修改、询问等一系列操作根据时间序列折半,将在操作离线。