单调队列--poj2823 Sliding Window

n个元素的数组,大小为k的窗口。

求窗口右滑时,窗口中的最大最小值。



#include <iostream>

#include <cstdio>

#include <deque>

#include <vector>

using namespace std;

struct pr{

    int num,pos;

};

int n,k;

deque<pr> dq1,dq2;//需要出队入队,所以

const int maxn = 1e6 + 5;

int v1[maxn],v2[maxn];


void seg_max(int t,int i)

{

    while (!dq1.empty() && dq1.front().pos <= i - k) {//先判断队首元素是否失效,是的话,先出队

        dq1.pop_front();

    }

    if(dq1.empty()) dq1.push_back(pr{t,i});//从队尾入队新的元素

    else{

        while(!dq1.empty() && dq1.back().num < t){//单调递减队列,区间最大值 //该处可以二分找

            dq1.pop_back();

        }

        dq1.push_back(pr{t,i});

    }

    v1[i] = dq1.front().num;

}

void seg_min(int t,int i)

{

    while (!dq2.empty() && dq2.front().pos <= i - k) {

        dq2.pop_front();

    }

    if(dq2.empty()) dq2.push_back(pr{t,i});

    else{

        while (!dq2.empty() && dq2.back().num > t) {

            dq2.pop_back();

        }

        dq2.push_back(pr{t,i});

    }

    v2[i] = dq2.front().num;

}

int read()

{

    int x=0,f=1;char ch=getchar();

    while(ch<'0' | ch>'9') {if(ch=='-') f=-1;ch=getchar();}

    while(ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}

    return x*f;

}

void Out(int aa)

{

    if(aa < 0){putchar('-');aa = -aa;}

    if(aa>9)

        Out(aa/10);

    putchar(aa%10+'0');

}


int main()

{

    n = read();k= read();

    int t;


    for (int i = 0; i < n; i ++) {

        t = read();

        seg_max(t, i);

        seg_min(t,i);

    }

    for (int i = k - 1; i < n; i ++) {

        Out(v2[i]);

        if(i == n - 1) putchar('\n');

        else putchar(' ');

    }

    for (int i = k - 1; i < n; i ++) {

        Out(v1[i]);

        if(i == n - 1) putchar('\n');

        else putchar(' ');

    }


    return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值