标签:class 处理 show pre 技术分享 复杂度 相交 lct src
很久以前考了一道叫做"林克卡特树"的题目( 还记得被八省联考支配的恐惧吗?)
正解是用直线去切一个凸函数......
当时并不是很会。然而\(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):
题目戳这里
可以发现,对于不在同一段的任意两个元素\(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')\)。
代码戳这里
题目戳这里
本质上就是要选择出\(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,1}\)有:
对于\(f_{u,j,2}\)有:
上述转移复杂度\(O(nK^2)\),不够优秀。
发现对于 表示选择个数的第二维\(j\) 可以进行斜率凸优化。
直接斜率凸优化即可,复杂度变为\(O(nlogK')\)。实现代码戳我。
标签:class 处理 show pre 技术分享 复杂度 相交 lct src
原文地址:https://www.cnblogs.com/GuessYCB/p/9051438.html