单调队列模板【附例题】
2020-05-05 16:00:23来源:博客园 阅读 ()
单调队列模板【附例题】
单调队列其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的。
每一个答案只与当前下标的前m个有关,所以可以用单调队列维护前m的个最小值,
考虑如何实现该维护的过程??
显然当前下标\(X\)的\(m\)个以前的元素(即下标小于\(X-M+1\)的元素)在范围外,和答案没什么太大联系,所以可以将其从队列中删除。
对于两个元素\(A\),\(B\),下标分别为\(a\),\(b\),如果有\(A>=B\)&&\(a<b\)那么B留在队列里肯定优于\(A\),因此可以将\(A\)删除。
维护队首:如果队首已经是当前元素的\(m\)个之前,将\(head\)++,弹出队首元素
维护队尾:比较\(q[tail]\)与当前元素的大小,若当前元素更优\(tail\)++,弹出队尾元素,直到可以满足队列单调性后加入当前元素。
考虑单调队列的时间复杂度:由于每一个元素只会进队和出队一次,所以为\(O(n)\)。
P1440 求m区间内的最小值
P1886 滑动窗口 /【模板】单调队列
P3088[USACO13NOV]Crowded Cows S
#include <bits/stdc++.h>
using namespace std;
int a[2000100];
bool b[2000100];
int q[2000100];//数组模拟队列,更好调试
int head=1,tail=0;
int n,m;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++)
{
while(i-q[head]+1>m&&head<=tail)//若头结点在范围外
{
head++;//弹出头结点
}
while(a[i]<a[q[tail]]&&head<=tail)//若当前节点优于尾节点
{
tail--;//弹出尾结点
}
q[++tail]=i;//当前节点入队
}
return 0;
}
利用单调队列,可以优化涉及定长连续子区间求最值的线性dp问题
例题
P1725 琪露诺 琪露诺是最强的!!
原文链接:https://www.cnblogs.com/IzayoiMiku/p/12832835.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- C++冒泡排序 (基于函数模板实现) 2020-05-31
- C++ 模板类vector 2020-05-31
- C++ 模板类array 2020-05-31
- C++ 模板类vector 2020-05-30
- 前缀和 2020-05-04
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash