分治算法例题

例0

u  二维平面上有一些点。有Q个询问,每个询问问横坐标不超过x,纵坐标不超过y的点的数目。可以离线。

u  这题的另一种形式是求逆序对。

u  正解:把所有点和询问排序,然后用树状数组即可求解。

例1

u  在一个初始为空的二维平面上,要求支持2种操作:

u  插入一个点

u  查询一个矩形内点的个数

u  坐标<=2*10^6

u  操作1数量<=160000

u  操作2数量<=10000

u  问题可以转化为:给定一个三维平面,每次求三维坐标在一个范围内的点的个数。

u  按x排序,然后考虑分治。

u  两边内部的答案可以递归计算。我们需要计算左边的点对右边的询问的贡献。

u  分别处理两边后,我们可以把左右按y排序,依次处理。对于x在左半边的点,按z坐标插入树状数组中,这样我们就可以快速统计出x在右半边的询问的答案了。

u  排序可以用归并来完成。

u  时间复杂度:O(nlog^2n)

u  这个算法是由cdq提出的,所以叫cdq分治。

例2

u  给定二维平面上的n个点,求最近点对

u  n<=10^5

u  考虑分治。

u  按x坐标排序,然后先求出左边一半和右边一半的解。

u  假设当前答案为d,那么找出距离中线(mid)小于d的点。

u  将这些点按y坐标排序。对于每个点,只需要求它和它上面8个点的距离并更新答案即可。

u  想一想,为什么?

u  事实上,这个数字还可以缩小。有兴趣的同学可以自行思考。

例5

u  N个物品有单价,收益,限购次数,第i个询问用w[i]的钱,在禁止购买ban[i]的情况下,能获得的最大收益

u  N<=1000    Q<=10^6    w[i]<=1000

u  考虑分治

u  对于全部的物品,对于右边一半的物品,左边一半的物品都对它有贡献

u  solve(l,r)表示,当前维护dp数组,记录的答案是出去[l,r]外的物品的答案

u  solve(l,mid)时用[mid+1,r]内的物品转移dp数组

u  当l=r时,将所有ban=l=r的询问一起(查dp数组)求答案

u  给定一张无向图(n<=700),每条边都有两个边权A和B

u  求一棵生成树,使得(所有边的A边权之和)*(所有边的B之和最小)

u  最小乘积模型:

u  考虑用二维平面上的点表示每一个解,其中x坐标表示其中一维权值和,y坐标表示其中另一维权值和。

u  每一个解对应的答案即为该点所在的反比例函数的k值。

u  很显然,最优解一定在凸壳上。

u  分治地去求这个凸壳。先求出x最小的解L,y最小的解R。

u  找到离AB这条直线最远(靠近原点方向)的解Mid。(想一想,怎么求?)

u  然后不停地分治,直到Mid离AB的距离为0。

u  每次求出一个新解时,就更新答案。

u  复杂度:玄学(n不大不小)

例1 cogs1752

例2 hdu1007

例5 bzoj3163

例6 bzoj2395

原文地址:https://www.cnblogs.com/ZYBGMZL/p/6796248.html