• 【集训队作业】line


    学习了新的斜率优化。

    斜率优化除了一般形式,还有另一个形式:

    $f_{i}=min(k*x+b)+v$

    其中k是个和x有关的常数,v是个常数,b是个和y有关的常数

    把k看做斜率,b看做截距,问题就是找一个j让这个直线的函数值最小,就是找一条平行于y轴的直线让函数值最小。

    是个李超树/动态半平面交的模板题。

    很多斜率优化都能规约到这个问题。

    如$f_{i}=min((a_{i}-a_{j})^2+f_{j})$

    拆开括号,$f_{i}=min(-(2*a_{j})*a_{i}+(a_{j}^2+f_{j}))+a_{i}^2$

    实际上,把k=-2*a[j],x=a[i],b=a[j]^2+f[j],就是这个问题。

    回到本题。这道题的dp方程$f[i]=min(max(t[j+1]...t[i])suf[i+1]+f[j]) j=l[i]~i-1$就是个斜率优化的形式。

    考虑cdq分治。考虑[l,md]对[md+1,r]的贡献。

    枚举[md+1,r]的节点i,设[md+1,i]的最大t值为v

    找到一个位置p,使得[p,md]的最大t值<=v而[p-1,md]>v

    [p,md]的部分中,对f的贡献变为f[i]=min(f[j])+v*suf[i+1],维护f的后缀最小值直接计算。

    [max(l,l[i]),p-1]中的斜率不受影响,可以直接预处理然后使用线段树查询。

    这题还能用树剖做。

    直接考虑维护max的过程。实际上在数据随机的时候,维护一个单调栈,单调栈的相邻两个数所代表的区间[s[i]+1,s[i+1]]的max值是相同的,记为val。

    dp方程变成了f[i]=min(val*suf[i+1]+f[j])。

    对于一个区间维护一条直线k=val,b=f[j],则在对应区间建立线段树即可查询。

    但是线段树在弹栈的时候的直线斜率会修改,十分麻烦。

    考虑一种不会破坏线段树的方法。

    如果在弹栈的时候把相邻两个栈的节点连边,最后把单调栈的相邻元素连边,则形成了一棵树。

    这棵树的性质是:一个点跳到根节点遇到的点就是要查询的。一个点跳到根的t是递增的。

    对于一个点维护直线$y=t_xx+min{f_{fa_x+1cdots x}}$。则每一次就是对到根节点的所有点查询s[i+1],是单调递减的。

    树剖+线段树维护。

  • 相关阅读:
    最受欢迎的ASP.NET的CMS下载
    asp.net开源CMS推荐
    Oracle分组小计、总计示例(grouping sets的使用)
    PLSQL登录的时候Warning提示:Using a filter for all users can lead to poor performance!
    hibernate saveorupdate方法只有更新有效果,保存没有效果
    Hibernate的generator属性
    在oracle中存入date类型数据遇到的问题及其解决方法(利用java.sql.date和Timestamp)
    Hibernate更新、删除后数据库无变化
    Oracle执行update时卡死问题的解决方法
    Hibernate
  • 原文地址:https://www.cnblogs.com/cszmc2004/p/12988430.html
Copyright © 2020-2023  润新知