zoukankan      html  css  js  c++  java
  • CF1190E

    题意

    给定(n)个点,以及(m),每个点向原点连有一条线段,你需要画(m)条直线,使得每个点的线段都存在某条线段经过(若该点为原点,则每条经过原点的直线都经过这条线段),求(m)条直线距离原点的最小值最大是多少。
    (n,mle 10^5)

    做法

    二分答案(r),那么考虑圆心为原点半径为(r)的圆。
    不应存在有点严格在圆的内部。

    容易证明,我们选取的直线与圆相切一定不劣。
    考虑每个点对圆的两个切点(有可能相同)的极角(l,r(lle r)),表示存在某条直线与圆切点的极角(in[l,r])

    然后我们将问题转化为

    给定(n)个区间([l,r]),是否可以选取(m)个点,使得每个区间都包含至少一个点

    如果这是在序列上做(注意该题的区间是在环上的),是存在经典的贪心:

    选取右端点最小的一个区间,选择右端点,除去包含该点的区间,反复操作知道不存在区间。

    而在环上,是不存在右端点最小的区间的(不存在偏序关系)。

    引理:存在最优解,使得每个点都位于某个区间的右端点。

    证明:
    对于一种选点的方式,可以将每个点从所在位置向右移,知道位于某个区间的右端点,显然这并不会使某个原来有点的区间现在无点。

    根据引理,可以枚举某个选了右端点的区间,然后以这个右端点作为数轴上(0)点,以右端点的大小定义偏序关系(特殊的,钦定该区间作为第一个区间),从而可以进行序列上的贪心,这样复杂度是(O(n^2logn))的。

    考虑破环成链,按右端点排序,再将每个区间复制一遍,左右端点增加(2pi),注意这里是按右端点定义偏序关系,所以开始的区间要保证右端点(in[0,2pi))。(在实际代码中,可以忽略精度,取([0,2pi])

    我们枚举某个区间(in[1,n]),其右端点选了点,然后便是([i,i+n))作为序列来做贪心。

    我们破环成链,虽然没有严格满足题意中的关系:可能有两点重合,但破环成链后这两点不为同一点。
    但在右端点相同,且选了该点作为第一个点时,取这类区间的第一个区间,是包含了这个解的。

    这样可以做到(O(n^2))

    注意到若我们已知选取了区间(i)的右端点,下一个贪心选取的区间(j(i<j))是确定的,故可以通过双指针的方式(O(n))确定下一个区间。再通过倍增得到选取区间(i)后,再选(2^k)个点所在的区间。
    可以在(O(nlogn)-O(nlogn))的复杂度内,检查(forall iin[1,n])作为第一个区间的合法性。

    总复杂度(O(nlognlogV))

  • 相关阅读:
    poj 1634
    poj 2153
    POJ 1693
    poj 1789
    POJ 2676
    vue 路由
    用 node.js 创建第一个Hello World
    js原生Ajax 的封装和原理
    BFC原理
    怎么理解js的面向对象编程
  • 原文地址:https://www.cnblogs.com/Grice/p/14521848.html
Copyright © 2011-2022 走看看