单调队列

单调队列是这样一个队列,队列中的所有元素是单调递增或者单调递减。它可以在队首或队尾删除元素,但是只能在队尾插入元素。由于每个元素入队和出队一次,所以维护队列的均摊时间复杂度为O(1)。


题目:http://poj.org/problem?id=2823


题意:给一个数组a[],求它连续m个元素中的最小值和最大值。比如输入:


8 3
1 3 -1 -3 5 3 6 7


那么输出:


-1 -3 -3 -3 3 3
3 3 5 5 6 7


分析:我们用一个数组q[]来记录这个单调队列所有元素的下标,h为队首,t为队尾。那么现在就来模拟样例:


首先h初始化为1,t初始化为0。


(1)插入第一个元素       q[] = {1},h = 1,t = 1    队列中的元素个数小于3,不输出。

(2)插入第二个元素       q[] = {1,2},h = 1,t = 2  队列中的元素个数小于3,不输出。

(3)插入第三个元素       q[] = {3},h = 1,t = 1    因为3号元素比1和2号元素都小,所以一直挤到最

                       前面,1号和2号元素出队,此时队列中的元素个数等于3,输出队首元素值。

(4)插入第四个元素       q[] = {4},h = 1,t = 1    同样的道理,3号元素出队,输出队首元素值。

(5)插入第五个元素       q[] = {4,5},h = 1,t = 2  输出队首元素。

(6)插入第六个元素       q[] = {4,6},h = 1,t = 2  输出队首元素。

(7)插入第七个元素       q[] = {6,7},h = 2,t = 3  输出队首元素。

(8)插入第八个元素       q[] = {6,7,8},h = 2,t = 4 输出队首元素。


#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;
const int N = 1000005;

int n,m;
int a[N],q[N];

void MinQ()
{
    int t = 0 ,h = 1;
    q[1] = 1;
    for(int i=1; i<=n; i++)
    {
        if(i - q[h] == m) h++;
        if(t == h-1 || a[i] > a[q[t]])
        {
            t++;
            q[t] = i;
        }
        else
        {
            while(t >= h && a[i] <= a[q[t]])
            {
                q[t] = i;
                t--;
            }
            t++;
        }
        if(i >= m) printf("%d ",a[q[h]]);
    }
    puts("");
}

void MaxQ()
{
    int t = 0 ,h = 1;
    q[1] = 1;
    for(int i=1; i<=n; i++)
    {
        if(i - q[h] == m) h++;
        if(t == h-1 || a[i] < a[q[t]])
        {
            t++;
            q[t] = i;
        }
        else
        {
            while(t >= h && a[i] >= a[q[t]])
            {
                q[t] = i;
                t--;
            }
            t++;
        }
        if(i >= m) printf("%d ",a[q[h]]);
    }
    puts("");
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
        scanf("%d",&a[i]);
    MinQ();
    MaxQ();
    return 0;
}

 


题目:http://acm.fzu.edu.cn/problem.php?pid=1894

 

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;
const int N = 1000005;

struct Node
{
    int id;
    int val;
    Node(int id = 0,int val = 0)
    {
        this->id = id;
        this->val = val;
    }
};

Node q[N];
char str[105];

int main()
{
    int T;
    scanf("%d",&T);
    q[0] = -1;
    while(T--)
    {
        scanf("%s",str);
        int i = 0,j = 1;
        int head = 1,tail = 0;
        while(scanf("%s",str))
        {
            if(!strcmp(str,"END")) break;
            if(str[0] == 'C')
            {
                int val;
                scanf("%s %d",str,&val);
                while(head <= tail && q[tail].val <= val) tail--;
                q[++tail] = Node(++i,val);
            }
            else if(str[0] == 'G')
            {
                while(head <= tail && q[head].id <= j) head++;
                j++;
            }
            else
                printf("%d\n",head > tail ? -1:q[head].val);
        }
    }
    return 0;
}


你可能感兴趣的:(单调队列)