1. 程式人生 > >用雙端佇列實現單調佇列

用雙端佇列實現單調佇列

單調佇列是指:佇列中元素之間的關係具有單調性,而且,隊首和隊尾都可以進行出隊操作,只有隊尾可以進行入隊操作。

以單調不減佇列為例:佇列內的元素(e1,e2,e3...en)存在(e1<=e2<=e3<=...<=en)的關係,所以隊首元素e1一定是最小的元素。與優先佇列不同的是,當有一個新的元素e入隊時,先要將隊尾的所有大於e的元素彈出,以保證單調性,再讓元素e入隊尾。

例如這樣一組數(1,3,2,1,5,6),進入單調不減佇列的過程如下:

1入隊,得到佇列(1);

3入隊,得到佇列(1,3);

2入隊,這時,隊尾的的元素3>2,將3從隊尾彈出,新的隊尾元素1<2,不用彈出,將2入隊,得到佇列(1,2);

1入隊,2>1,將2從隊尾彈出,得到佇列(1,1);

5入隊,得到佇列(1,1,5);

6入隊,得到佇列(1,1,5,6);

程式碼實現

這個程式碼是實現單調不遞減的佇列

#include<bits/stdc++.h>
const int N=1e6+10;
using namespace std;
int a[N];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        memset(a,0,sizeof(a));
        int i;
        deque<int>num;
        for(i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
        }
        num.push_back(a[1]);
        int a1,a2;
        for(i=2; i<=n; i++)
        {
            if(!num.empty())
                a1=num.back();
            while(1)
            {
                if(a1<=a[i]||num.empty())
                {
                    num.push_back(a[i]);
                    break;
                }
                else if(!num.empty())
                {
                    num.pop_back();
                   if(!num.empty())
                    a1=num.back();//3
                }
            }
        }
        while(!num.empty())
        {
            printf("%d ",num.front());
            num.pop_front();
        }
        printf("\n");
    }
    return 0;
}