首页 > 其他分享 >CDQ 分治学习笔记

CDQ 分治学习笔记

时间:2023-02-16 10:15:19浏览次数:51  
标签:偏序 排序 分治 笔记 CDQ 区间 数据结构

CDQ 分治学习笔记

简介

CDQ 分治一般用来解决偏序问题。我们先来回忆一下:

  • 一维偏序:排序即可解决问题。
  • 二维偏序:对于 \((a,b)\),我们使用排序解决 \(a\),然后 \(b\) 使用树状数组即可简单维护。
  • 三位偏序:有一维不好处理,怎么做呢?

这时候,CDQ 分治即使一个不错的解决方法。在允许离线的情况下,CDQ 可以在 \(O(n\log^2n)\) 的复杂度内解决三维偏序。

其实,我们有一个简单的解决方法:排序,然后使用二维数据结构解决二维剩下的偏序问题。但是鉴于那样的数据结构相对更为复杂、代码复杂度更高,所以 CDQ 还是很不错的。

算法

我们使用排序解决第一维,一维数据结构(比如树状数组)解决第三维。然后第二维,我们使用分治算法解决。具体来说:

对于一个区间 \((l,r)\),我们将其分为 \((l,mid)+(mid+1,r)\),然后递归计算两个区间的贡献,再计算两个区间之间的贡献(其实类似于线段树的思路)。假如两个子区间的贡献已经搞定了,那我们此时只需要计算左区间对于右区间的贡献。此时,我们左区间每个数可以理解为 \((0,b,c)\),右边则是 \((1,b,c)\)——此时,相当于转换为二维偏序。因此,我们可以使用排序加上树状数组解决。具体来说,我们使用归并排序,遇到左区间的数就加入数据结构,遇到右区间的数就查询数据结构。这样即可在 \(O(len\log len)\) 的复杂度内解决某一个区间中单独的贡献,然后总的复杂度就是 \(O(n\log^2 n)\)。

我们来分析一下这个算法的本质。为什么只用一个简单的分治,即可解决需要用高级数据结构才能解决的问题呢?我的理解,就是降维——高维问题转换为低维问题。我们原本是一个 \(O(n)\) 规模的三维问题,然后用一个分治将其转换为了一个 \(O(n\log n)\) 的二维问题——这个就是精髓。非常奇妙。

那么现在,我们来尝试解决一下四维偏序——虽然没有什么实际用处,但是可以加深理解。

P3769 [CH弱省胡策R2]TATT

我们有一个简单的做法:排序,然后用三维数据结构解决剩下的三维。这个当然是可行的,只需要一个 KD-Tree 即可,也不失为一种优秀的做法。

或者,一维排序然后数据结构套数据结构(树状数组+KD-Tree),也很优秀。

或者,一维排序一维 CDQ,剩下的使用二维数据结构——可行,但是应该既不好写又不优秀。

甚至,你可以直接使用 KD-Tree 解决四维偏序,只不过复杂度巨大无比而已。

而当然,CDQ 是可行的。我们排序一维,一维数据结构搞定一维,中间两维都使用 CDQ。

我们先排序然后第一层分治,问题转换为:前一半子区间 \((0,b,c,d)\) 对于后一半子区间 \((1,b,c,d)\) 的贡献。注意,我们需要计算这个区间第一维所有 \(0\) 对于 \(1\) 的贡献

然后对于这一个区间,按照 \(b\) 排序。然后接着分治下去。接下来,问题就转换为 \((0,0,c,d)\) 对于 \((1,1,c,d)\) 的贡献。然后就使用二维的方法解决即可。

复杂度的话考虑一个位置会被操作 \(O(\log^2)\) 次,加上数据结构总共就是 \(O(n\log^3n)\),但是常数很小。

非常有意思。

标签:偏序,排序,分治,笔记,CDQ,区间,数据结构
From: https://www.cnblogs.com/One-coder/p/17125687.html

相关文章

  • 《分布式技术原理与算法解析》学习笔记Day13
    分布式计算模式:MapReduce什么是分治法?分治法是将一个复杂、难以直接解决的大问题,分割成一些规模小、可以比较简单或者直接求解的子问题,这些子问题之间相互独立且与原问题......
  • PLC入门笔记10
    梯形图电路之顺序控制顺序控制功能图  顺序控制功能图的梯形图表达编程原则实例分析        ......
  • TCC---分布事务4 笔记20230215
            ......
  • 读Java实战(第二版)笔记11_语言特性和类库更新
    1. 注解1.1. 一种使用附加信息装饰程序元素的机制1.2. Java8之前,只有声明可以被注解1.3. 一种语法元数据(syntacticmetadata)1.4. 可以用于文档编制1.4.1. @De......
  • C#快速入门 _笔记
      https://www.youtube.com/watch?v=Mz-8PpvflaQ&list=PLJgD_fXVXZKppT4stJ09s9nu3byvyMERE&index=20 20.访问修饰符private:私有的,仅类的内部可以访问protected:......
  • Python学习笔记(一)环境确认
    1.安装环境1)python解释器版本3.10.2安装完毕后在命令提示符窗口中输入python显示版本信息2)开发工具pycharm 2021.1.32.新建项目  创建项目后修改解释器配置可......
  • 学习笔记Redis篇
    这篇仅仅为今日刷Redis课的一点小小总结,一点遗忘小细节罢了1.@Resource和@Autowire的区别CSDN地址:https://blog.csdn.net/u012102104/article/details/79481007二者都......
  • JS笔记(四):面向对象、异常处理
    镇楼图Pixiv:torino六、JS中的面向对象类(class)博主视为你已拥有相关基础,这里不再赘述相关概念类的语法如下,class在本质上是function,可以说class只是针对构造器的......
  • 《分布式技术原理与算法解析》学习笔记Day12
    调度框架:共享状态调度什么是共享状态调度?共享状态调度是为了解决单体调度和两层调度遇到的问题而创建出来的新的调度框架。它通过将单体调度器分解为多个调度器,每个调度......
  • Java编译异常捕捉与上报笔记
    异常处理机制的作用:增强程序的健壮性处理编译异常方式一:在方法声明位置上使用throws关键字抛出,谁调用该方法,就交给谁处理注意:为Exception的是需要处理的,否则编译器会报......