单调栈(G - Sliding Window POJ - 2823 )

题目链接:https://cn.vjudge.net/contest/276251#problem/G

题目大意:给你n和m,然后问你对于(m,n)这中间的每一个数,(i-m+1,i)这个区间的最小值和最大值。

具体思路:单调队列,对于个数的控制,我们通过队列来实现一个模拟的滑动窗口。然后最值的寻找,我们可以通过控制队列保持单调递增或者单调递减来实现。

STL AC代码(耗时:10985s):

 

#include<iostream>
#include<stack>
#include<cmath>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
# define inf 0x3f3f3f3f
# define ll long long
const int maxn = 1e6+100;
int minn[maxn],maxx[maxn],sto[maxn];
inline int read1()
{
    int f=1,x=0;
    char s=getchar();
    while(s<'0' || s>'9')
    {
        if(s=='-')
            f=-1;
        s=getchar();
    }
    while(s>='0' && s<='9')
    {
        x=x*10+s-'0';
        s=getchar();
    }
    return x*f;
}
int main()
{
    int n,m;
    n=read1();
    m=read1();
    // scanf("%d %d",&n,&m);
    deque<int>q1;
    deque<int >q2;
    int tot=0,tmp;
    for(int i=1;i<=n;i++){
    sto[i]=read1();
    }
    for(int i=1; i<=n; i++)
    {
        while(!q1.empty()&&q1.front()<i-m+1)//先判断左边界有没有超出范围
            q1.pop_front();
        while(!q1.empty()&&sto[i]<sto[q1.back()])//保持队列单调递增
        {
            q1.pop_back();
        }
        q1.push_back(i);
        if(i>=m)
            minn[++tot]=q1.front();
        while(!q2.empty()&&q2.front()<i-m+1)
            q2.pop_front();
        while(!q2.empty()&&sto[i]>sto[q2.back()])
        {
            q2.pop_back();
        }
        q2.push_back(i);
        if(i>=m)
            maxx[tot]=q2.front();
    }
    for(int i=1; i<=tot; i++)
    {
        if(i==1)
            printf("%d",sto[minn[i]]);
        else
            printf(" %d",sto[minn[i]]);
    }
    printf("\n");
    for(int i=1; i<=tot; i++)
    {
        if(i==1)
            printf("%d",sto[maxx[i]]);
        else
            printf(" %d",sto[maxx[i]]);
    }
    printf("\n");
    return 0;
}

数组模拟(耗时:7152ms)AC代码:

#include<iostream>
#include<stack>
#include<cmath>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
# define inf 0x3f3f3f3f
# define ll long long
const int maxn = 1e6+100;
int minn[maxn],maxx[maxn],sto[maxn];
int moni[maxn];
inline int read1()
{
    int f=1,x=0;
    char s=getchar();
    while(s<'0' || s>'9')
    {
        if(s=='-')
            f=-1;
        s=getchar();
    }
    while(s>='0' && s<='9')
    {
        x=x*10+s-'0';
        s=getchar();
    }
    return x*f;
}
int main()
{
    int n,m;
    n=read1();
    m=read1();
    int l=1,r=0;
    int tot=0;
    for(int i=1; i<=n; i++)
    {
        sto[i]=read1();
    }
    for(int i=1; i<=n; i++)
    {
        while(l<=r&&moni[l]<i-m+1)
            l++;
        while(l<=r&&sto[i]<sto[moni[r]]){
            r--;
        }
             moni[++r]=i;
        if(i>=m)
            minn[++tot]=moni[l];
    }
    l=1,r=0,tot=0;
    for(int i=1; i<=n; i++)
    {
        while(l<=r&&moni[l]<i-m+1)
            l++;
        while(l<=r&&sto[i]>sto[moni[r]]){
            r--;
        }
             moni[++r]=i;
        if(i>=m)
            maxx[++tot]=moni[l];
    }
    for(int i=1; i<=tot; i++)
    {
        if(i==1)
            printf("%d",sto[minn[i]]);
        else
            printf(" %d",sto[minn[i]]);
    }
    printf("\n");
    for(int i=1; i<=tot; i++)
    {
        if(i==1)
            printf("%d",sto[maxx[i]]);
        else
            printf(" %d",sto[maxx[i]]);
    }
    printf("\n");
    return 0;
}

(我太菜了,,,数组模拟调了半个小时。。)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值