最近在整理原来的一些资料,偶然想起原来搞OI时讲过一次CDQ分治的内容,这里分享给大家
目录
CDQ分治是一种特殊的分治方法,在OI界初见于陈丹琦2008年国家集训队作业中
预备知识
常见递归复杂度
先来分析下面这个递归方程:
其时间复杂度如何分析?
将式子迭代两次得:
继续迭代,整理得:
我们发现式子的结构特别像一个树形结构,由此可引出递归树法:
图中的(a)(b)(c)(d)分别是递归树生成的第1,2,3...N步。每一节点中都将当前的自由项n^2留在其中,而将两个递归项T(n/2) + T(n/2)分别摊给了他的两个子节点,如此循环。
图中所有节点之和为:
因此原递归方程的时间复杂度为O(n^2)
可以得到递归树法的规则为:
(1) 每层的节点为T(n) = kT(n / m) + f(n)中的f(n)在当前的n/m下的值;
(2) 每个节点的分支数为k;
(3) 每层的右侧标出当前层中所有节点的和。
那么通过该方法,可以推出这些式子:
- T(n)=2T(n/2)+O(kn)的解是T(n)=O(kn log n)
- T(n)=2T(n/2)+O(kn log n)的解是T(n)=O(kn log^2n)
- T(n)=2T(n/2)+O(k)的解是T(n)=O(kn)
分治思想
问题:给定序列Ai,求序列中的逆序对数
方法:归并排序实现:定义归并排序过程Merge(l,r)
Merge(l,r)
¤Merge(l,mid)
¤Merge(mid+1,r)
¤Count(l,mid,mid+1,r)
由于之前已执行过merge(1,mid),那么[l,mid]之间的元素是有序的,因此若i∈[l,mid],j∈[mid+1,r],若有a[i]>a[j]成立,则答案加上mid-i+1
CDQ分治例题
货币兑换
此题为NOI2007一试第二题
其实解决这个问题的突破口在提示:
设f[i]表示第i天全部将A,B券换成人民币的最多数目,p[i].a表示A券在第i天最多拥有的个数,p[i].b表示B券在第i天最多拥有的个数,则:
那么,对于第i天最后一次购买,它在第j天(i<j)的折合人民币就是:
于是:
因此,我们得到一个动态规划的算法,框架如下:
p[1].b=S / (A[1] * Rate[1] + B [1])
Ans=S
For i = 2 to n ← 枚举在哪一天卖出券
For j = 1 to i-1 ← 枚举在哪一天买入券
x=p[ j ].a * A[i ] + p[j ].b * B [i ]
Ans=max{Ans,x}
End For
p [i ].b = Ans / (A[i ] * Rate[i ] + B[i ])
End For