「刷题」分治

  分治,大多复杂度在$ O(log_2n) $ 级别,因为每次递归把大小减半,所以最多$ log_2n $层,今天做的点分和$CDQ$都是这样的。

  先总结一下$CDQ$,很强的数据结构,不知道陈丹琦怎么做到$ noi $现场$yy$这么一个数据结构出来实在是$TQL$,昨天学过了之后今天上午11点左右才开始做题,找了几个板子刷了一下,然后写了自己的板子。

  主要思想就是以时间为轴,进行分治,不断递归子问题,最终得到一个不可分割的可以立刻得到解的子问题,但是和普通的分治不一样。普通的分治必须满足每一个子问题是和原问题解决方法相同,结构相同的子结构。而$ CDQ $分治不一样,她计算的时候分别计算左右区间,再加上跨越中点的代价或者贡献进行合并,得出子结构的解,从而完成一次递归,这样可以解决不可分割的具有整体性的区间问题。

  大多数时候$ CDQ $分治适用于三维偏序问题。

  现在说一下怎么实现的,$ CDQ $分治又被称基于时间的分治算法,一般都是以各种操作的时间顺序为轴进行分治,这里满足分治的先后顺序,就可以直接计算左区间对右区间的影响,从而达到跨区间计算贡献的目的。

  那么第一维就是时间了。第二维可以靠单调指针扫描解决,第三维就需要树状数组等类似的数据结构来维护,所以三维偏序问题的时间复杂度一般都是$ O(nlog_2^2n) $ ,一些优化就是第二维可以利用归并排序的思想进行维护,从而减去很大的常数。

  说一下$CDQ$分治优化$dp$。

  一般情况下的$CDQ$都是先递归左右区间再处理当前区间。但是优化$dp$一般都是先处理左区间,然后处理中间区间,再处理右区间,这样可以让后面的$dp$值被已经更新过的$dp$值更新,从而保证$dp$的正确性。

  对于一个形如:

    $dp[i]=max limits_{a_i leq a_j}^{b_i leq b_j}{dp[j]}+1$

  的状态转移方程。

  我们可以很好的找到一个三维偏序问题,也就是对于一个位置$ i $,它以前的所有$ dp $值可以用于更新他,而我们按照$ dp $数组的更新时间去维护时间轴,然后维护剩下两个维度$a$和$b$,找出时间、$a$、$b$均小于$i$的$j$,并用他的$dp$值去更新当前的$i$的$dp$值。

  很容易发现之前那种递归顺序是错的,因为先儿子后自己很可能导致右侧的左儿子部分的$dp$值不能被左侧的左右儿子更新,所以我们先递归左儿子,用左儿子在递归父亲处更新右区间,再递归右区间,执行相同的左右分治操作。

这样可以使得每次$dp$被更新的值永远是最新的。

  

  下面是静态点分。

  总的来说有两种方法,一种是容斥去重,一种是子树归并,其实本质上还是用分治去优化$dp$,点分让那些严重以来树型结构的$dp$得以用较高的复杂度在较低的次数中完成。

  容斥一般来说就是计算的时候会计算子树内所有的贡献,但是在递归儿子的时候有些贡献会被重复计算,因为他的儿子就属于他的子树,这个时候再减去儿子的一些贡献即可去重。

  子树归并总的来说类似于树型背包的写法,让不同的子树在归并的过程中产生时间差,从而不重不漏的计算子树的贡献,和复杂度证明一样,子树归并保证贡献的计算是按照点对数目计算的。

  

  今天只做了几道$CDQ$和一道优化$dp$的$CDQ$,以及几道基础的静态点分,学长讲的动态点分和虚树还都没有写过题,但是明天上午考试,又要该题,估计和线段树剩下那五道一样,这六道也要留到开学了吧。

  革命尚未成功,同志仍需努力。

原文地址:https://www.cnblogs.com/Lrefrain/p/11252935.html