CDQ 学习笔记

CDQ 学习笔记

什么是 CDQ

\(CDQ\) 算法本质上来说其实是一种思想。用来处理点对之间的位置关系,优化一维 \(dp\),或者是将一些动态问题转化为静态问题。

\(CDQ\) 是一种离线做法,对于某个区间查询而言,虽然直接计算该区间很困难,但当只有一个点时处理起来简单,并且如果将原区间分为左右两个区间时可以较为容易的算出左区间对右区间的贡献时,就可以使用 \(CDQ\) 分治解决问题。

\(CDQ\) 的基本操作

通常来说,\(CDQ\) 的操作为以下几个步骤:

  1. 将原区间从中间分开分成左区间和右区间。
  2. 分别递归左右区间。
  3. 当该区间长度为 \(1\) 时,计算目前贡献,结束递归。
  4. 计算左区间对右区间的贡献。

从三维偏序开始

先来一道版题:P3810 【模板】三维偏序(陌上花开)

大概题意是:

有 $ 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 \ne i $ 的 \(j\) 的数量。对于 $ d \in [0, n) $,求 $ f(i) = d $ 的数量。

先搞掉一维,也就是先按照 \(a\) 排序,接着进行 \(CDQ\) 基本操作。

考虑如何计算左区间对右区间的贡献。

首先由于在最开始的时候已经按照 \(a\) 排序了,所以左区间的 \(a\) 值一定小于右区间的 \(a\) 值,这样三维偏序就变成了二维偏序。

接着,按照 \(b\) 的大小分别对左右区间排序,再拿树状数组记一下即可。

至于为什么在按 \(b\) 排序的时候不会对其他产生影响,是因为每次操作,我们都是先递归下去然后进行计算的,所以小区间对大区间自然不会产生影响了。

好了,你已经学会三维偏序了,去做这些题吧:

P3810 【模板】三维偏序(陌上花开)

P3157 [CQOI2011] 动态逆序对

P3364 Cool loves touli

P3658 [USACO17FEB]

到二维数点

其实和三维偏序差不多,有的时候只是静态二维数点的话甚至不需要使用\(CDQ\),只是可能有的题会有修改操作时需要用到 \(CDQ\) 进行三维偏序的处理。

习题:
P2163 [SHOI2007] 园丁的烦恼 不带修

P4390 [BalkanOI2007] Mokia 摩基亚 带修

\(CDQ\) 优化 \(dp\)

通常情况下是对于一些具有大小关系的 \(dp\) 转移进行优化。

简单来说就是仍然需要拥有三个偏序关系。

与普通 \(CDQ\) 不太一样的是 \(CDQ\) 优化 \(dp\) 需要先处理左边的部分,然后 \(dp\) 计算贡献,再把序列还原,然后递归处理右边。

练习题:

P4093 [HEOI2016/TJOI2016] 序列


The End

posted @ 2023-12-07 19:16  Populus_euphratica  阅读(16)  评论(0)    收藏  举报