cdq分治:从归并到cdq套cdq

感谢 mlystdcall 的透彻讲解

本文里没有的代码可以去这里查看


前置芝士

cdq分治可以用来解决多维偏序问题

优点:代替复杂数据结构,代码好写(类似归并排序),常数小

缺点:必须离线

重要原则:cdq分治归根到底是分治,只用考虑分治后左边对右边的影响,其他的都是递归下去的子问题

原则不懂可以先记住,边看边理解


二维偏序

例:给定N个有序对(a,b),求对于其中的每个的(A,B),满足a<A且b<B的有序对(a,b)有多少个?

逆序对问题,换了个马甲而已。

各种数据结构都能水过去

这里的二维很显然,就是一个a,一个b

建议用归并排序练习一下

排序前位置递增,排序后大小递增,在排序的时候统计逆序对。

归并是cdq的雏形,不能说毫不相干,只能说一模一样

带修改的类二维偏序

例:
有一个n个元素的序列,初始值全部为0,有两种操作:

操作1:格式为1 x k,把位置x的元素加上k。

操作2:格式为2 x y,求出区间[x,y]内所有元素的和。

P3374 【模板】树状数组 1好家伙,马甲都没换

各种数据结构都能水过去

用cdq怎么做?

先找二维分别是啥

第一维是时间顺序(操作顺序),很容易被忽略

第二维是操作(询问可以用前缀和的思想拆分为两个位置)的位置

归并排序前时间递增,排序后位置递增,排序中统计。

这里详细讲一下。

归并的时候将lr分为了lmid(简称L)和mid+1~r(简称R)两块。

一个修改(设为X)怎么才能对一个询问(设为Y)产生影响?X的时间和位置都比Y靠前

L里的时间都比R早,L里边已经按照位置排好序了(但时间是乱的),R也一样。

双指针对L和R的位置处理一下就行了,顺便统计。

三维偏序

P3810 【模板】三维偏序(陌上花开) 好家伙,马甲都没了

模板题而已

一维排序,二维cdq,三维树状数组

你也可以试试套一下别的

建议看着代码理解

代码看这里

四维偏序/cdq套cdq

例:给定n个有序四元组(a,b,c,d),求对于每一个四元组(A,B,C,D),有多少个四元组(a,b,c,d)满足a<A && b<B && c<C && d<D。

其实就是三维偏序加了一维

套娃开始了

其实我们可以把这里的(c,d)看做三维偏序里的(c),那么刚才的树状数组就要换成能维护二维信息的数据结构,空间&时间复杂度爆炸

我们思考一下,cdq优点有哪些?它能把具体的数值变成L和R的区分,省去了比较的过程。我们以L和R区分为基础(此时就省去了一维),再处理剩下的几维。

按照这个思路,我们cdq的时候其实就是分为了(aL,b,c,d)和(aR,b,c,d),我们顺便记录一下每个元素按照a是属于aL还是属于aR

我们把这个复制一遍,按照b排序(此时a的乱的,但是根据a带有L或R的标记),我们顺便记录一下每个元素按照b是属于bL还是属于bR

此时每个元素就是分为了(aL/aR,bL/bR,c,d)

要是想造成贡献,只能是(aL,bL,c,d)对(aR,bR,c,d)造成的

然后c这一维双指针,d这一维树状数组


练习题:
P3810 【模板】三维偏序(陌上花开)三维偏序
P5459 [BJOI2016]回转寿司 题解
P4093 [HEOI2016/TJOI2016]序列
P4169 [Violet]天使玩偶/SJY摆棋子
[HZOI 2016]偏序 COGS 2479 四维偏序
[bzoj2989&4170: 数列]

原文地址:https://www.cnblogs.com/wljss/p/14965909.html