zoukankan      html  css  js  c++  java
  • 李超线段树

    李超线段树

    因为太弱了,所以只会用单调队列、CDQ分治、平衡树来维护凸壳,然后被(zjp\_shadow)聚聚在博客底下给D了一顿,所以辣鸡yyb就来学一下了。
    (似乎整个机房就我不会了)

    首先先明白这个东西在干啥

    你要资磁动态维护一个平面直角坐标系,资磁在中间插入一条线段,资磁询问与(x=x0)这条直线相交的所有线段中,交点的(y)轴坐标的最大(小)值。

    我们要维护的东西是这个:维护这个区间内的所有直线中,从上往下能够看到的最长的那个线段,也就是没有被其他直线覆盖长度最大的段。

    考虑怎么插入一条直线,假设它当前处理到了某个区间:

    • 如果这个区间没有记录最长的线段,那么直接把这个区间记录的线段修改为这条线段,然后返回。
    • 如果当前线段在这个区间内已经被这个区间内的最长线段为覆盖,那么直接(gg),返回就好了。
    • 反过来,如果完全覆盖了之前记录的线段,那么直接赋值、返回。
    • 否则和已经记录的直线有交,判断哪根线段覆盖的区域较长,把这个区间记录的值给修改一下,然后把短的那一半丢下去递归。

    这样子复杂度是啥呢?显然维护复杂度看起来不太对的就是最后一项,但是不难证明每次递归下去直线长度都至少要减少一半,所以这个东西的复杂度就是一个(log)的。
    至于询问?那就是单点询问啦,在线段树上一直走到这个单点为之,把路径上所有记录的线段拿出来取一个(max)就好啦。

    比如BZOJ1568就是模板题QwQ。
    当然了,上面这题是每次插入一条直线,这样子只需要一个(log),如果每次插入一条线段的话还是要稍微变一下的,即要先找到对应的区间再在这个区间内插入这个线段,这样子复杂度是两个(log)的,代码戳这里


    然后(zjp)说可以用李超线段树直接维护斜率优化,想了想的确可以,我这里随便搬一道题目过来。

    [HNOI2010]玩具装箱

    首先写暴力(O(n^2))的转移,设(S_i)(C_i)的前缀和。

    [f[i]=min_{j=0}^{i-1}f[j]+(i-j-1+S_i-S_j-L)^2 ]

    [f[i]=min_{j=0}^{i-1}f[j]+(i-j-1)^2+(S_i-S_j-L)^2+2(i-j-1)(S_i-S_j-L) ]

    然后把式子拆开,和(j)无关的直接移出去,只和(j)相关的放在一起,同时和(i,j)相关的放在一起。
    那么分类之后就是这样的:
    (j)无关的:(i^2-2i+1+S_i^2+L^2-2LS_i+2iS_i-2iL-2S_i+2L)
    只和(j)有关的:(f[j]+j^2+2j+S_{j}^2+2LS_j+2jS_j+2jL+2S_j)
    同时和(i,j)相关的:(-2ij-2S_iS_j-2iS_j-2jS_i=-2(i+S_i)(j+S_j))
    一共(22)项,似乎没有什么问题。(其实可以直接令(M_i=i-1+S_i-L),但是为了锻炼拆式子能力就这样吧......算了,我编不下去了.....)
    那么把和(j)无关的部分记做(pre[i]),只和(j)有关的记做(y[j])(j+S_j)记做(x[j])(2(i+S_i))记做(k_i)
    那么转移方程可以改写成:

    [f[i]=pre[i]+min_{j=0}^{i-1}(-k_ix[j]+y[j]) ]

    (k_i)是一个常数,我们把后面这个式子理解为一个一次函数(y=kx+b)的形式,得到(b=y-kx)
    什么意思呢?平面上有若干个点((x[j],y[j])),你要过这些点画一条斜率为(k_i)的直线,使得其截距最小。
    不难发现满足条件的(j)一定在下凸壳上。
    这里有个很优秀的性质,也就是(k_i,x[j])都是单增的。
    这样子凸壳可以直接用单调队列维护,而取最优值只需要每次找到凸壳左侧最优位置就好啦。

    上面是直接用斜率优化,然后单调队列维护凸壳的做法(我直接从别的文章里蒯过来的)
    那么我们把那个式子换一下,把(y[j])写成(b[j])(-x[j])写成(k[j])
    那么转移就是

    [f[i]=pre[i]+min_{j=0}^{i-1}2(i+S_i)k[j]+b[j] ]

    于是问题变成了,平面上有若干条直线,现在你要询问在(x=2(i+S_i))处的最小值,所以可以直接使用李超线段树来维护。(虽然复杂度多了一个(log))。

  • 相关阅读:
    c# linq查询的等于大于符号是什么意思?
    c# Socket tcpClient处理连接超时方式timeout
    不同网段服务器与客户端连接问题解决方法TCP/IP_C/S
    Http请求响应及SpringMVC相关注解解析
    Nginx部署项目,转发规则,负载均衡配置
    Linux redis设置后台启动
    Linux centos7安装Jdk nginx redis
    SpringCloud整合SpringSecurity JWT进行认证 ,鉴权
    C#中class与struct的区别概述
    列举ASP.NET 页面之间传递值的几种方式
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10560973.html
Copyright © 2011-2022 走看看