CF868F Yet Another Minimization Problem (四边形不等式 trick)

题意:给定序列,把序列分成 k 段,使每一段相同元素对数之和最小。n105,k20,ain

容易写出转移方程:dp[i][j]=mink=1i(dp[k1][j1]+w(k,i)),其中 w(k,i) 表示 akai 的相同元素对数。


第一想法是 wqs 二分,然后发现 w(k,i) 实在太恶心了,既没办法拆贡献也没办法快速计算。

其次考虑四边形不等式优化。w(l,r) 满足四边形不等式的性质比较显然。

然后考虑到二分队列。遇到了同样的问题:w(l,r) 没办法快速计算,也就没办法快速比较段首和 i 的决策孰优孰劣。

思路卡住了。于是这里有一个新的技巧:类莫队在分治过程中维护 w

考虑用分治的方法做,即枚举 d=1k,每一次把 dp[?][d] 求出来。

设当前到 slv(l,r,posl,posr),表示求 dp[lr][d],这一段的最优决策点在 [posl,posr] 里。

按照一般的流程,接下来我们会取 m=(l+r)/2,然后枚举 j=poslm,找到 dp[j1][d1]+w(j,m) 最小的 j,令 dp[m][d]=dp[j1][d1]+w(j,m) 然后分治计算 slv(l,m1,posl,j)slv(m+1,r,j,posr)

再次遇到了一样的问题:w(j,m) 难以计算!!!

但是这里我们有解决办法。我们考虑开全局变量 l,r,cnt[],sum 记录当前记录了区间 [l,r]cnt 数组和 w。类似莫队。在我们询问 w(j,m) 时,直接暴力挪动左右端点获取答案。

正确性显然,问题是复杂度怎么是对的。

从上一层 [L,R] 的最后一次计算转移到本层 [L,M] 的第一次计算,复杂度是 O(posRposL) 的。站在 [L,R] 的角度看,无论 slv(L,M),slv(M,R) 干了什么事,它转移到下一层的工作最多是 O(posRposL) 次移动端点:把当前层端点移动到 slv(L,M) 所需的位置是 RL 次,再移动到 slv(M,R) 位置也是 RL 次。

而在一层内部,移动次数总共是 O(n) 的。因为一层内的 [posl,posr] 是不相交的。

所以总复杂度是 O(nlogn)

posted @   FLY_lai  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示