zoukankan      html  css  js  c++  java
  • 分治算法例题

    例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

  • 相关阅读:
    mongodb的安装与启动(centos7)
    使用tengine解决负载均衡的session问题
    nginx 负载均衡 使用ip_hash方式解决session问题 测试
    查看linux服务器状态常用命令
    swagger
    使用gtest(googletest)进行c++单元测试
    程序员的字符艺术
    使用gdb调试c++程序
    使用c++开发跨平台的程序
    Orleans之EventSourcing
  • 原文地址:https://www.cnblogs.com/ZYBGMZL/p/6796248.html
Copyright © 2011-2022 走看看