单调队列 POJ 2823

本文介绍单调队列的概念及其在动态规划中的应用。解释了单调队列如何存储元素的位置和状态值,并保持这些值的单调性。同时给出了具体的插入和删除操作实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个题只能开输出挂才能过 ,单调队列因为要操作前面的和后面的,所以要用双向队列

引用:

一.       什么是单调(双端)队列

单调队列,顾名思义,就是一个元素单调的队列,那么就能保证队首的元素是最小(最大)的,从而满足动态规划的最优性问题的需求。

单调队列,又名双端队列。双端队列,就是说它不同于一般的队列只能在队首删除、队尾插入,它能够在队首、队尾同时进行删除。

【单调队列的性质】

一般,在动态规划的过程中,单调队列中每个元素一般存储的是两个值:

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;
}





                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值