陌上花开 CDQ分治
传送门:
题意:
\[ 有n 个元素,第 i 个元素有 a_i、 b_i、 c_i 三个属性,设 f(i) 表示满足 a_j\leq a_i 且 b_j \leq b_i且 c_j \leq c_i的 j 的数量。\\ 对于 d \in [0, n],求 f(i) = d 的数量 \]
题解:
CDQ分治模板题,
我们将第一维在主函数排序后,cdq分治里面,每次将左半边和右半边按照y排序,因为一开始的x是已经排序过了的,所以分治将其分为左半边和右半边时,左半边的x还是小于右半边的x,因此维护右半边的位置i和左半边的位置j,如果y[j]<y[i]的话,我们就可以将z[j]丢进树状数组中,直到y[j]>=y[i]时,不满足偏序关系的时候,我们就可以直接树状数组查询小于z[i]的前半部分的j的个数,这样,这么多个数就满足三维的偏序关系。
1.x的偏序关系已经在主函数里面处理,所以分治分了后前一半的x小于后一半的x
2.y的偏序关系是两个指针对着扫了,一遍,将满足y[j]<y[i]的z[j]丢进了树状数组统计个数
3.z的偏序关系是从树状数组中查的小于z[i]的z[j]有多少个
一直这样分治下去,我们就可以得到最终的答案
这个题有一个坑点就是,当x,y,z都相同时,在分治的时候,本来它们相互之间都有贡献,可是cdq的过程中只有左边的能贡献右边的。这可怎么办呢?我们直接离散化后,给定一个权值,这样算贡献就不会算错了
代码:
#include #include