【CCC2019】 Tourism
题目大意
将一个长度为 n 的序列分为 ⌈kn⌉ 段且每一段的长度不超过 k,求每一段的最大值的和。
数据范围满足,1≤k≤n≤106。
思路
考虑暴力的 dp,定义 fi,j 表示前 i 个分成 j 段的答案。
fi,j=l=i−kmaxi−1(fl,j−1+r=l+1maxi(ar))
考虑如何优化这个 dp,显然枚举过程已经是最优,只能从状态上简化。
可以发现这样一个事实,我们之前枚举的大部分状态对于最终的答案都是没有贡献的。借此,我们发现对于 i,只有 fi,⌈ki⌉ 对之后的答案有贡献。证明如下:
- 若 j<⌈ki⌉,那么必定有一段长度大于 k。
- 若 j>⌈ki⌉,由上分析可知后面最少也要 ⌈kn−i⌉ 段,所以有 j+⌈kn−i⌉>⌈ki⌉+⌈kn−i⌉⩾⌈kn⌉ 一定不满足。
所以记 gi=fi,⌈ki⌉,根据如上的方程,能够向 gi 贡献的只有满足 i−k⩽j⩽i−1 且 ⌈ki⌉−1=⌈kj⌉ 的 j,所以方程为:
gi=j=i−kmaxk×⌊ki−1⌋(gj+k=j+1maxiak)
对于 maxk=j+1iak 考虑使用单调栈进行求解,对于 gi 的区间最大值使用线段树维护,其时间复杂度为 O(nlogn)。
记录详情 - 洛谷 | 计算机科学教育新生态 - luogu.com.cn