POj 2823 Sliding Window 单调队列

题意:给出n和k ,求在n个数里每隔k个数求出其中的最小值和最大值并分别输出

思路:采用单调队列

单调队列的性质:

在动态规划的过程中,单调队列中每个元素一般存储的是两个值:
1、在原数列中的位置(下标)
2、在动态规划中的状态值

用一个数组模拟队列,记录下标

坑爹,我几乎调了两个小时,一直TLE,找位置改用二分法还是T了,最后想放弃了,然后用c++交A了!可怜我花了那么长时间

代码:

#include<iostream>
#include<cstdio>
using namespace std;
const int MAX = 1000001;
//两个单调队列
int dq1[MAX];  //存递减 
int dq2[MAX];  //存递增
int a[MAX];
inline bool scan_d(int &num)
{
    char in;
    bool IsN=false;
    in=getchar();
    if(in==EOF)
        return false;
    while(in!='-'&&(in<'0'||in>'9')) in=getchar();
    if(in=='-')
    {
        IsN=true;
        num=0;
    }
    else num=in-'0';
    while(in=getchar(),in>='0'&&in<='9')
    {
        num*=10,num+=in-'0';
    }
    if(IsN)
        num=-num;
    return true;
}

int main(void)
{
    int i,n,k,front1,front2,tail1,tail2,start,ans;

    while(scanf("%d %d",&n,&k)!=EOF)
    {
        for(i = 0 ; i < n ; ++i)
            scan_d(a[i]);
        front1 = 0, tail1 = -1;
        front2 = 0, tail2 = -1;
        ans = start = 0;
        for(i = 0 ; i < k ; ++i)
        {
            while(front1 <= tail1 && a[ dq1[tail1] ] <= a[i])
                --tail1;
            dq1[ ++tail1 ] = i;

            while(front2 <= tail2 && a[ dq2[tail2] ] >= a[i])
                --tail2;
            dq2[ ++tail2 ] = i;
        }
        //输出最小值
        printf("%d ",a[ dq2[ front2 ] ]);
        for( ; i < n ; ++i)
        {
            while(front2 <= tail2 && a[ dq2[tail2] ] >= a[i])
                --tail2;
            dq2[++tail2] = i;
            while(dq2[ front2 ] <= i - k)
                ++front2;
            if(i!= n-1)
                printf("%d ",a[ dq2[ front2 ] ]);
        }
        printf("%d\n",a[dq2[ front2 ]]);

        //输出最大值
        printf("%d ",a[dq1[ front1 ]]);
        for(i=k ; i < n ; ++i)
        {
            while(front1 <= tail1 && a[ dq1[tail1] ] <= a[i])
                --tail1;
            dq1[ ++tail1 ] = i;
            while(dq1[ front1 ] <= i - k)
                ++front1;
            if(i != n-1)
                printf("%d ",a[ dq1[ front1 ] ]);
        }
        printf("%d\n",a[ dq1[ front1 ] ]);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值