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

题意:给定序列,把序列分成 \(k\) 段,使每一段相同元素对数之和最小。\(n\le 10^5,k\le 20,a_i\le n\)

容易写出转移方程:\(dp[i][j]=\min_{k=1}^{i}(dp[k-1][j-1]+w(k,i))\),其中 \(w(k,i)\) 表示 \(a_k\sim a_i\) 的相同元素对数。


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

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

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

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

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

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

按照一般的流程,接下来我们会取 \(m=(l+r)/2\),然后枚举 \(j=posl\sim m\),找到 \(dp[j-1][d-1]+w(j,m)\) 最小的 \(j\),令 \(dp[m][d]=dp[j-1][d-1]+w(j,m)\) 然后分治计算 \(slv(l,m-1,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(posR-posL)\) 的。站在 \([L,R]\) 的角度看,无论 \(slv(L,M),slv(M,R)\) 干了什么事,它转移到下一层的工作最多是 \(O(posR-posL)\) 次移动端点:把当前层端点移动到 \(slv(L,M)\) 所需的位置是 \(R-L\) 次,再移动到 \(slv(M,R)\) 位置也是 \(R-L\) 次。

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

所以总复杂度是 \(O(n\log n)\)

posted @ 2024-12-11 20:11  FLY_lai  阅读(21)  评论(0)    收藏  举报