• [IOI2015]分组


    如果把一个限制((a,b))视为平面上的一个点。
    小组的人数是((x,x))
    题目的限制要求(a<=x<=b)就是(a<=x)(x<=b)
    则平面上在((a,b))左上方的无穷大的平面的小组代表的点都是当前点((x,x))能取的。要取(x)个。
    考虑一个贪心。把所有小组按照(x)从小到大排序。
    则显然我们尽量取纵坐标最小的点最优。
    这是因为纵坐标更大的点更容易能被后面的(x)取。坐标越小的点更容易失去覆盖机会。
    这样子我们可以解决前面的部分分。
    要解决此题,需要发现更好的性质。
    引理1:在任何时刻,横坐标为(i)的点中,被覆盖的点的纵坐标一定是个连续的区间。
    引理2:设(h_i)为横坐标为(i)的点中,被覆盖的点的最大高度。则(h_i<=h_{i+1})
    可以使用反证法。设(j)为第一个点满足(h_j>h_{j+1})。则如果把(j)的一些点给(j+1),依然符合要求。
    反复运用此操作,最后一定能调整到(h_i<=h_{i+1})
    把询问的所有值从小到大排序。
    显然使用一个单调栈维护(h)。把连续相同的(h)缩成一个元素。
    h可以表示一个折线。
    在插入一个左下角为((x,x))的矩形后,删除栈顶所有纵坐标(<x)的点。
    现在栈顶的点的纵坐标(>=x),所以((x,x))可以取栈维护的折线上的所有点。
    (r_i)表示栈中第i个元素在栈中所对应的直线的右端点的左上,在折线上方的元素的个数。
    我们先统计横坐标在([st_{tp},a_i]),纵坐标在([a_i,inf])的点的个数。显然可以可持久化线段树。
    如果点数(<a_i)则返回0。
    否则扫描栈中的所有元素。
    我们栈中右部的点数为(p),设剩余我们需要匹配的点数为(pp),则(pp-=p)
    (v=r_{po}-pp)表示上面需要二分的点数。
    把线段树上矩形([st[tp],i])的点拿出来把纵坐标从大到小排序,然后求出删除上面(v)个点后剩下的点的最大横坐标(pv)
    如果pv>栈顶元素,则删除栈顶元素,更新pp。
    显然可以线段树二分解决。
    综上,我们在(nlog_2n)时空复杂度内解决了此题。
    维护栈的过程十分玄学。

  • 相关阅读:
    Ubuntu下彻底卸载mysql
    Navicat连接Ubuntu中的MySQL,报错1130-host
    win10优化开机进程
    导入别人工程后项目报错,有个小红叉
    eclipse中的tomcat配置
    解决eclipse启动慢
    linux screen命令
    python pip install出现问题
    scala中执行shell命令
    spark 累加器
  • 原文地址:https://www.cnblogs.com/ctmlpfs/p/13731502.html
Copyright © 2020-2023  润新知