cdq分治 笔记
算法讲解
这个算法用于解决三维偏序问题。
三维偏序:给定 \(n\) 个三元组: \((a_i,b_i,c_i)\),求同时满足满足 \(a_i\le a_j,b_i\le b_j,c_i\le c_j\) 的 \((i,j)\) 的数量。
那这该咋求呢⊙(・◇・)?
先把维度降下来,二维偏序,会不会做?就是求多少个 \((i,j)\) 满足 \(a_i\le a_j,b_i\le b_j\)。
显然,先按照 \(a\) 排一下序。然后就变成了 \(i<j,b_i\le b_j\) 的问题了。可以用树状数组做。最典型的案例就是逆序对问题,这个都写熟练了哈(*╹▽╹*)
三维偏序的问题,也是先按 \(a\) 排一下序。然后接下来的问题考虑分治(这样的分治过程被我们称为“cdq分治”)
假设我们要求 \([l,r]\) 中的答案。已经求好了 \([l,mid],[mid+1,r]\) 中的答案,现在只需要考虑跨区的答案了。
那么我们可以把 \([l,mid]\) 和 \([mid+1,r]\) 内部都按照 \(b\) 排序。因为我们只要考虑跨区的答案,那么我们把两边分别都随便排序,对跨区的时候 \(a\) 的大小关系没有影响。然后我们在 \([mid+1,r]\) 中枚举一个元素 \(j\),找到在 \([l,mid]\) 中有多少个 \(i\) 满足 \(b_i\le b_j\),然后这个 \(i\) 显然是递增的。然后我们一边单调的维护这个 \(i\) ,一边用树状数组维护 \(c_i\le c_j\) 的数量即可。