学习笔记: cdq分治

今年的课程有很大一部分内容是cdq分治及其扩展(也就是二进制分组),拜读后觉得还是蛮有用的,这里小小地总结一下。(话说自己草稿箱里还有好多学习笔记的半成品呢,真是弱爆了。顺便感谢下fy与wxl向我介绍了那么好的东西)

推荐论文:

1 《从<Cash>谈一类分治算法的应用》 陈丹琦

2 《浅谈数据结构题的几个非经典解法》  许昊然

Q: cdq分治和普通的分治有什么区别?

A: 在我们平常使用的分治中,每一个子问题只解决它本身(可以说是封闭的)。而在cdq分治中,对于划分出来的两个子问题,前一个子问题用来解决后一个子问题而不是它本身。

在很多问题中(比如大多数数据结构题),我们经常需要处理一些动态问题。然而我们对动态问题的处理总是不如静态问题来的那么方便,于是就有了cdq分治。但正如论文2所提到的,使用这算法的前提是问题必须具有以下两个性质:

1.修改操作对询问的贡献独立,修改操作互不影响效果。

2.题目允许使用离线算法。

具体算法流程如下:

1.将整个操作序列分为两个长度相等的部分(分)

2.递归处理前一部分的子问题(治1)

3.计算前一部分的子问题中的修改操作对后一部分子问题的影响(治2)

4.递归处理后一部分子问题(治3)

{

  cdq分治的大概步骤就是
1. Solve(l,mid)
2. Solve(mid+1,r)
3. 处理左边对右边的影响

}

在整个流程中,最核心的就是步骤3:因为前一部分子问题中的修改操作相对后一部分子问题来说是静态处理,所以我们就可以更加方便地计算后一部分子问题。

CDQ分治属于比较特殊的一类分治,许多问题转化为这类分治的时候,时空方面都会有很大节省,而且写起来没有这么麻烦。

这类分治的特殊性在于分治的左右两部分的合并,作用两部分在合并的时候作用是不同的,比如,通过左半部分的影响来更新右半部分,所以分治开始前都要按照某一个关键字排序,然后利用这个顺序,考虑一个区间[l, r]的两部分间的影响。

时间: 2024-10-24 17:58:45

学习笔记: cdq分治的相关文章

【cdq分治】cdq分治与整体二分学习笔记Part1.整体二分

之所以把cdq分治和整体二分放在一起学习,是因为他们两个实在太像了-不管是做法还是代码- 感觉整体二分可能会比cdq分治稍微简单那么一点点?所以先学整体二分.(感觉他们的区别在于整体二分是对每个操作二分答案,cdq是分治了操作序列) 整体二分是对答案进行二分,其具体操作如下: (比如以ZJOJ2013K大数查询为例) 具体过程 Step1.从(L,R)二分答案.mid=(L+R)>>1,用线段树维护原序列中(a,b)位置比mid大的数有多少个,同时记录对序列的操作分别是什么操作. Step2.

CDQ 学习笔记

CDQ分治 CDQ(陈丹琦)分治是一种特殊的分治方法. 它只能处理非强制在线的问题. CDQ分治在维护一些动态的凸包.半平面交问题也有一定应用,然而本渣渣并不会. CDQ分治基于时间分治,整体二分基于答案分治. 步骤 1:将操作按照某个关键字排序 2:算出[L,mid]对[mid+1,R]的贡献 3:递归处理[L,mid]和[mid+1,R] 注:这里的区间指的是操作区间. 题目必须满足“修改独立,允许离线”两个条件. 这样的话我们把操作区间二分 会发现后一半的修改操作对前一半的询问操作不会产生

动态点分治学习笔记

学习动态点分治之前要先弄清楚点分治的原理,二者的应用范围的不同就在于动态的支持在线修改操作,而实现的不同就在于动态点分治要建点分树. OI中有很多树上统计问题,这类问题往往都有一个比较容易实现的暴力做法,而用高级数据结构维护信息有显得过于复杂,有没有一种"优美的暴力",能既保证思维的简单性,又有更高效的时间复杂度保证呢?这就是点分治的思想. 点分治的实现过程是:每次找到当前树的重心,然后以这个重心为根统计这个树的信息,然后对重心的每个孩子分别递归,同样用将重心作为根的方法统计子树的信息

[用CDQ分治解决区间加&区间求和]【习作】

[前言] 作为一个什么数据结构都不会只会CDQ分治和分块的蒟蒻,面对区间加&区间求和这么难的问题,怎么可能会写线段树呢 于是,用CDQ分治解决区间加&区间求和这篇习作应运而生 [Part.I]区间加&区间求和的数据结构做法 [一]线段树 裸题... 1141ms #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include

CDQ分治与整体二分总结

Cdq分治和整体二分是两个很奇妙的东西.他们都是通过离线的思想来进行优化,从而更快的求出解. 整体二分通俗的讲就是二分答案,但是它了不起的地方是一下子把所有的答案都二分出来了,从而可以一下子得出所有查询. CDQ分治通俗的讲就是二分查询.通常的做法是把所有的查询分成两半,然后通过递归先计算出左边一半的所有的查询,然后通过这些已知的左半边的值来更新右半边的值.这里,最最重要的思想是通过左半边来更新右半边.更具体一点,就是用左半边的修改来更新右半边的查询. 重要的事情说话三遍: CDQ分治就是通过左

《数据结构与算法分析》学习笔记(二)——算法分析

一.对算法分析方法的最简单的理解和使用方法 1.首先大家可能一般会被那些数学的概念搞晕,其实简单理解下来,就是假设任何语句执行的效率都是一样的,所以设定每一个语句的执行时间都是一个时间单位,那么只要计算这个程序到底执行了多少语句,就可以算出其时间复杂度. 2.其次就是我们要明白,我们是个估算,所以可以进行化简,明显我们可以忽略那些相对来说低阶的项,只分洗最高阶项.然后主要就是有这些常见的法则: (1)FOR循环 一次for循环的运行时间至多是该for循环内语句的运行时间乘以迭代次数. (2)嵌套

[学习笔记]数据结构与算法

1.排序简单排序:?冒泡排序:将n个数从上往下排列,从第0个数开始依次对前n个.前n-1个.前n-2个数进行比较,保持小数在前大数在后,不符合就交换.在这个过程中,最后一个数始终是最大数.?选择排序:对所有n个.后n-1个.后n-2个依次比较,用一个变量存最小数,一趟比较完成之后,将最小数与所比较数据的第一个数进行交换.在这个过程中,第一个数始终是最小数.?插入排序:从第1个数开始向前扫描比较,小则插入.对于未排序数据,在已排序序列中向前扫描,并找到相应的位置插入.在这个过程中,整个序列局部有序

Android学习笔记-回顾计划

人最怕的是,没有方向! 1.楔子: 本人接触Andrjoid开发也有一年多了,期间在一家外包公司独立开发了五六个项目.虽谈不上大牛,但自认小有所成.平时没什么爱好,就喜欢看看技术博客,试验各种开源代码,写写学习笔记. 最近感觉有点陷入瓶颈了,进步甚慢,却又不知该如何进一步提升自己.对于开发中遇到的很多问题,虽有所领悟,然不够系统,一些小知识点,也常有遗漏.觉得是时候系统的反思一下自己的知识体系了,于是决定制定一个回顾计划,综合自己看的博客.书籍,以及自己的开发实践,对一些常用的知识点进行整理.

由LCS到编辑距离—动态规划入门—算法学习笔记

一切计算机问题,解决方法可以归结为两类:分治和封装.分治是减层,封装是加层. 动态规划问题同样可以用这种思路,分治. 它可以划分为多个子问题解决,那这样是不是用简单的递归就完成了?也许是的,但是这样会涉及太多的不便的操作.因为子问题有重叠! 针对这种子问题有重叠的情况的解决,就是提高效率的关键. 所以动态规划问题可以总结为:最优子结构和重叠子问题. 解决这个子问题的方式的关键就是:memoization,备忘录. 动态规划算法分以下4个步骤: 描述最优解的结构 递归定义最优解的值 按自底向上的方