單調隊列 POJ 2823

這個題只能開輸出掛才能過 ,單調隊列因爲要操作前面的和後面的,所以要用雙向隊列

引用:

一.       什麼是單調(雙端)隊列

單調隊列,顧名思義,就是一個元素單調的隊列,那麼就能保證隊首的元素是最小(最大)的,從而滿足動態規劃的最優性問題的需求。

單調隊列,又名雙端隊列。雙端隊列,就是說它不同於一般的隊列只能在隊首刪除、隊尾插入,它能夠在隊首、隊尾同時進行刪除。

【單調隊列的性質】

一般,在動態規劃的過程中,單調隊列中每個元素一般存儲的是兩個值:

1.      在原數列中的位置(下標)

2.      他在動態規劃中的狀態值

而單調隊列則保證這兩個值同時單調。

 從以上看,單調隊列的元素最好用一個類來放,不這樣的話,就要開兩個數組。。。

 插入方法(以最大單調隊列爲例):

在插入一個元素前,先判斷隊列是否爲空(head<=tail),然後再判斷隊尾元素是否比要插入的元素小(q[tail].val<data[insert]),如果是的話,則將隊尾元素刪除(--tail)。

重複以上過程,直至爲空或隊尾元素比其大。

刪除方法:

    這個要根據具體題目而定。在本題是如果當前的INDEX與隊首的INDEX相差大於等於K,則刪除。

#include<stdio.h>
#include<deque>
#include<vector>
#include <limits.h>
#include<algorithm>
using namespace std;

typedef pair<int,int> P;

deque<P> qMax;
deque<P> qMin;


inline void putint(int n)
{
    static char buf[20];
    register int pos;
    register int x = n;
    if (x == 0) {
        putchar('0');
        return;
    }
    if (x == INT_MIN) { // x = -x do not work for the minimal value of int, so process it first
        printf("%d", x);
    }
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    pos = 0;
    while (x > 0) {
        buf[pos] = x % 10 + '0';
        x /= 10;
        pos++;
    }
    pos--;
    while (pos >= 0) {
        putchar(buf[pos]);
        pos--;
    }
}



void pushMax(int n,int i)
{
    while(!qMax.empty()&&qMax.back().first<=n)
    {
        qMax.pop_back();
    }

    qMax.push_back(P(n,i));
}
void pushMin(int n,int i)
{
    while(!qMin.empty()&&qMin.back().first>=n)
    {
        qMin.pop_back();
    }
    qMin.push_back(P(n,i));
}

vector<int> mins;
vector<int> maxs;

int main()
{
    int n,k;

   while(scanf("%d%d",&n,&k)!=EOF){
        if(k>n)
            k=n;
        while(!qMin.empty()) qMin.pop_back();
        while(!qMax.empty()) qMax.pop_back();
        mins.clear();
        maxs.clear();

    for(int i=0;i<k-1;i++)
    {
        int num;
        scanf("%d",&num);
        pushMin(num,i);
        pushMax(num,i);
    }
    for(int i=k-1;i<n;i++)
    {
        int num;
        scanf("%d",&num);

        pushMax(num,i);
        pushMin(num,i);
        if(i-qMin.front().second>=k)
            qMin.pop_front();
        if(i-qMax.front().second>=k)
            qMax.pop_front();
        maxs.push_back(qMax.front().first);
        mins.push_back(qMin.front().first);

    }
    for(int i=0;i<mins.size();i++)
    {
        putint(mins[i]);
        if(i!=maxs.size()-1)
        putchar(' ');
    }
    printf("\n");
    for(int i=0;i<maxs.size();i++)
    {
        putint(maxs[i]);
        if(i!=maxs.size()-1)
        putchar(' ');
    }
   }
    return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章