ACM-单调队列

对于单调队列的基本概念可以去看百科里的相关介绍:http://baike.baidu.com/view/3771451.htm

这里挑一些重点。

作用:

不断地向缓存数组里读入元素,也不时地去掉最老的元素,不定期的询问当前缓存数组里的最小的元素。
最直接的方法:普通队列实现缓存数组。
进队出队都是O(1),一次查询需要遍历当前队列的所有元素,故O(n)。

RMQ即Range Maximum(Minimum) Query,用来求某个区间内的最大值或最小值。使用线段树或稀疏表是O(log(n))级的。对于这类问题这两种方法也搞得定,但是没有单调队列快。

定位:

大多数题目为单调队列力所不能及的,取而代之的是单调队列基础上改进的斜率优化,单调栈等,因为其限制条件,故潜力不大。但需要掌握,因为有许多算法建立在其基础上。

简单说就是基础,得会。

poj 2823

http://acm.hust.edu.cn/vjudge/problem/16694

k大小的滑动窗口,求每次窗口中最大值和最小值

思路:

维护单增队列和单减队列,因为滑动窗口和index有关,所以加个index数组维护head的索引

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <cctype>
#include <vector>
#include <iterator>
#include <set>
#include <map>
#include <sstream>
using namespace std;

#define mem(a,b) memset(a,b,sizeof(a))
#define pf printf
#define sf scanf
#define spf sprintf
#define pb push_back
#define debug printf("!
")
#define MAXN 1000000+5
#define MAX(a,b) a>b?a:b
#define blank pf("
")
#define LL long long
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define pqueue priority_queue
#define INF 0x3f3f3f3f

#define ls (rt<<1)
#define rs (rt<<1|1)

int n,m,k;

int a[MAXN],qu[MAXN],index[MAXN],ans[MAXN];

void getMin()
{
    int head=1,tail=0;
    for(int i =1;i<k;i++)
    {
        while(head<=tail && a[i]<=qu[tail]) tail--;
        qu[++tail] = a[i];
        index[tail] = i;
    }
    for(int i=k;i<=n;i++)
    {
        while(head<=tail && a[i]<=qu[tail]) tail--;
        qu[++tail] = a[i];
        index[tail] = i;
        while(index[head]<= i-k) head++;
        ans[i-k] = qu[head];
    }
}

void getMax()
{
    int head=1,tail=0;
    for(int i =1;i<k;i++)
    {
        while(head<=tail && a[i]>=qu[tail]) tail--;
        qu[++tail] = a[i];
        index[tail] = i;
    }
    for(int i =k;i<=n;i++)
    {
        while(head<=tail && a[i]>=qu[tail]) tail--;
        qu[++tail] = a[i];
        index[tail] = i;
        while(index[head]<= i-k) head++;
        ans[i-k] = qu[head];
    }
}

int main()
{
    int i,j,t,kase=1;
    while(~sf("%d%d",&n,&k))
    {
        for(i=1;i<=n;i++) sf("%d",&a[i]);
        getMin();
        for(i=0;i<=n-k;i++) pf("%d ",ans[i]);
        blank;
        getMax();
        for(i=0;i<=n-k;i++) pf("%d ",ans[i]);
        blank;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/qlky/p/5789225.html