A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低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问题

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马