CDQ分治学习笔记

CDQ 分治是一种离线的分治思想,可以用来处理以下问题:

  • 解决和点对有关的问题。
  • 1D 动态规划的优化与转移。
  • 通过 CDQ 分治,将一些动态问题转化为静态问题。
    (摘自 oiwiki)

解决和点对有关的问题

算法流程如下:
要解决 [l,r] 的问题,先将 [l,mid],[mid+1,r] 的问题解决,再解决整个区间的问题,所以不严格得讲,分治求平面最近点对、归并排序都是 CDQ 分治的思想(但是 CDQ 分治一般会套上数据结构)。

例:三维偏序#

我们要求 [1,n] 中的点对 (i,j),先分治,解决 [1,mid],[mid+1,n] 的子问题,再考虑 limid,mid+1jr 的点对,我们先在一开始让数组按 ai 升序排序,保证 limid<jr,ajai,然后再左右分别按 bi 升序排序,这是为了方便我们双指针找到所有满足 bibji,接下来就不用多说了,用树状数组把 ci 存起来然后计算即可。

Code

注意:cmp1 不仅要按 ai 排,还要在 ai 相同时按 bi,ci 排,否则可能会让满足条件的点对 (i,j) i 在右边而统计不到, cmp2 则不用(但建议还是写一下)

例2:[CQOI2011] 动态逆序对#

tii 被删除的时间,如果没有被删除则 ti=+,然后考虑一个点 i 删除前后,删除后少去了其本身当前的贡献,也就是点对 (i,j) 满足 ti>tj((i<jvali>valj)(i>jvali<valj)),这就转化成了一个三维偏序问题。

Code

优化动态规划的转移

其实和点对之间的关系的处理是同理的,但是要注意的是,处理跨越区间 (i<mid<j)的问题时,要按照正确的 dp 转移顺序来。例如,我们有一个二维的 LIS 问题,转移方程为:
dpi=maxj=1i1[aj<aibj<bi]dpj
这里我们之间一个 cdq 分治上去,树状数组维护前缀最大值就能优化到 O(nlog2n), 但是中间的处理部分必须要放在 cdq(l, mid) 和 cdq(mid+1, r) 之间,因为在转移 i 的时候要求 j<idpj 都被处理完了。如果 l=r, 则说明 dpl 处理完毕了,直接 return 即可。

例:[SDOI2011] 拦截导弹#

如上,第一问跑一个二维最长非升子序列即可,但是第二问,我们需要求出存在 i 的最长非升子序列个数,除以总个数,这里有个 trick,只要求出以 i 结尾、开头的最长非升子序列个数,再相乘即可(如果两者拼起来的长度为全局最长长度的话),那么目标明确,两边 CDQ 就行,细节有点多,可以慢慢理解下代码。

Code

将动态问题转化为静态问题

这里,CDQ 分治折半的是 时间序列,也可以说是操作(修改和询问)顺序序列,常用于解决 修改 xxx 询问 xxx 的问题,但是这是个离线算法,我们要先把所有修改、询问存下来,这样操作本身就按时间排好序了,这时,每个修改都会影响到后面的询问,这样的点对共有 O(n^2) 对。称为一个修改-询问关系,下面我们用 i 来表示第 i 次操作。
接下来思路便明了了,我们在解决 (l,r) 中所有修改和询问问题时,先处理 (l,mid),(mid+1,r) 之间的关系,再处理 (i,j)(limidjr) 的关系,其中 i 是一个修改,j 是一个询问。

有一点要注意的是,如果修改之间相互 , 比如区间加减什么的,这时候我们随便什么时候处理

作者:循环一号

出处:https://www.cnblogs.com/Loop1st/p/18701591

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   循环一号  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示