可查询双端队列学习笔记

1|0可查询双端队列

操作:头插头删,尾插尾删,查最大值。

做法:从中点维护向左、向右两个单调栈(不强制加入),如果一个单调栈被删空了就重构。

复杂度证明:一次重构的复杂度是两个单调栈的长度差,而每次操作最多使长度差 +1,于是总复杂度是 O(n) 的。

1|1P1295 [TJOI2011] 书架

题意:给一个序列 h,要分成若干段使得每一段长度不大于 m,最小化所有段的最大值之和。

思路:首先可以很简单的想到一个 O(n2) 的 DP:设 fi 表示 i 为当前段末尾的最小和,则 fi=minsisj<=m(fj+maxk=j+1ihk)

因为有最大值,我们考虑找找单调性。首先,如果 hjhj+1,那么 maxk=jihk=maxk=j+1ihk,而 f 显然是单调递增,那这个时候从 j转移一定比从 j+1 转移更优,所以我们很容易用一个单调队列(记为 q)来记录可能对答案做贡献的位置。然后我们考虑如何计算贡献。因为队列里的值是递减的,即 hql>hqr,那么每个的贡献就是 fql+aql+1,这时我们还需维护 f。为了保证复杂度,我们可以用两个单调下降的栈来维护 f,每当左或右端点到了中点就重构,这样复杂度就是 O(n) 的了。


__EOF__

本文作者Xttttr
本文链接https://www.cnblogs.com/Xttttr/p/18014449.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Xttttr  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示