zoukankan      html  css  js  c++  java
  • 斜率凸优化小结

    斜率凸优化小结

    前言

    很久以前考了一道叫做"林克卡特树"的题目( 还记得被八省联考支配的恐惧吗?)
    正解是用直线去切一个凸函数......
    当时并不是很会。然而(APIO)讲课竟然讲了并且卧槽我竟然还听懂了。
    所以就回来把这个坑给填了。

    斜率凸优化

    当遇到关于需要恰好选取(K)个的(DP)问题的时候,
    一般做法就是在(DP)数组上再设一维。这样做时间代价是(O(n))的。
    其实不如给每次选取加一个权值(C)
    那么每次选取就需要付出(C)的代价。所以(C)越大选的越少,(C)越小选的越多。
    所以?二分(C)即可。时间代价变为(O(logn))
    形象的来说,对于(DP)数组,取(E)个时的答案(best(E))是一个上凸的。
    所以我们用(f(x) = Cx)这条直线去切这个上凸包,直到(best(K)-KC)是最优的。
    那么此时选取的个数就是题目所需的(K)个了。
    下面给一张图(引用自cjfdf):

    例1:[APIO2014]序列分割

    题目戳这里
    可以发现,对于不在同一段的任意两个元素(a),(b),都对答案有(ab)的贡献。
    所以处理出前缀和(pre)
    那么转移:(f_{i,j} = max{f_{k,j-1} + pre_k * (pre_i - pre_k)})
    斜率优化不解释,复杂度(O(nK)),可以直接通过原题。
    如果(K leq 200) 变为(K leq n)呢? 直接斜率凸优化即可,复杂度(O(nlogK'))
    代码戳这里

    例2:[八省联考2018]林克卡特树lct

    题目戳这里
    本质上就是要选择出(K+1)条不相交的路径使它们的权值和最大。
    考虑树形(DP)。设(f_{u,j,0/1/2})分别表示(u)点的度数为(0/1/2)时的最优解。
    定义(Ans_{u,j})表示(max{f_{u,j,0/1/2}})
    转移:
    对于(f_{u,j,0})有:

    • (f_{u,j,0} = max{ f_{u,j-t,0} + Ans_{v,t} })

    对于(f_{u,j,1})有:

    • (f_{u,j,1} = max{ f_{u,j-t,1} + Ans_{v,t}})
    • (f_{u,j,1} = max{ f_{u,j-t,0} + f_{v,t,1} + Edge_{u,v}})
    • (f_{u,j,1} = max{ f_{u,j-t-1,0} + f_{v,t,0} + Edge_{u,v}})

    对于(f_{u,j,2})有:

    • (f_{u,j,2} = max{ f_{u,j-t,2} + Ans_{v,t}})
    • (f_{u,j,2} = max{ f_{u,j-t+1,1} + f_{v,t,1} + Edge_{u,v}})

    上述转移复杂度(O(nK^2)),不够优秀。
    发现对于 表示选择个数的第二维(j) 可以进行斜率凸优化。
    直接斜率凸优化即可,复杂度变为(O(nlogK'))。实现代码戳我

  • 相关阅读:
    什么是反向代理,反向代理有什么好处?
    动态的favicons
    管理emacs dotemacs文件
    自己的部分小软件合计 2000 2013(很久没有更新了)
    经典CSS 横向导航菜单【下载】
    Web 调试,兼容浏览器的在线调试(系列)
    sql server 执行大脚本时报警告没有足够的内存继续执行程序
    c#对接顺丰图片文件
    Sql Server行转列 动态拼接sql
    centos6.2更新yum源
  • 原文地址:https://www.cnblogs.com/GuessYCB/p/9051438.html
Copyright © 2011-2022 走看看