基础算法 - CDQ 分治
简介
CDQ 分治解决三维偏序问题,在接触它之前,先来看一下二维偏序问题。
Stars(二维偏序)
给定 n 个点,定义每个点的等级是在该点左下方(含正左、正下)的点的数目,试统计每个等级有多少个点。
题目链接:LOJ 10114。
对于这种问题,可以按照字典序排序,然后可以用归并排序的分治算法或者树状数组解决这个问题。这里已经按照 Y,X 字典序排好序了,并且保证没有重复的点,所以我们只需要读入 X 即可。
树状数组
1 |
|
归并排序
1 |
|
三维偏序
有 个元素,第 个元素有 三个属性,设 表示满足 且 且 且 的 的数量。
对于 ,求 的数量。
题目链接:AcWing 2815,P3810。
我们需要将二维偏序中的两种思路结合起来,就能解决三维偏序问题,这也是 CDQ 分治的模板。
在此之前,我们需要手动实现一个类似 std::unique
的去重函数,并且能统计出来每个元素出现了多少次,大概长下面这样:
1 | // q[i].s should be 1 at first |
但是,其实我们可以用 set
解决这个问题。
1 | // q[i].s should be 1 at first |
复杂度显然都是 ,而且肯定是上面那种写法常数小,实测能快一倍。
很显然,对于相同的元素,它们是满足偏序性质的,所以最终一个元素的偏序值是计算出来的结果加上 ,其中 代表与它相同的元素的数量(包括它自己)。
1 |
|
[CQOI 2017] 老C的任务
给定 个点,每个点 ,再给 个查询,每次查询 区域内所有点的 之和。
题目链接:AcWing 2487,P3755。
对于在 CDQ 分治中的 坐标,令点 ,查询
这里用前缀和的思想,每个查询存四个点,所以这就要存一下在统计答案的时候应该加还是减了,用一个 sgn
表示符号。
1 |
|
[CQOI 2011] 动态逆序对(待补)
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 喵喵小窝!