zoukankan      html  css  js  c++  java
  • 单调栈&单调队列

    单调栈

    定义

       单调栈是指一个栈内部的元素是具有严格单调性的一种数据结构,分为单调递增栈和单调递减栈。

    性质:
       ① 满足从栈顶到栈底元素具有严格的单调性。
       ② 满足栈的后进先出特性,越靠近栈底的元素越早进栈。

    单调队列

    定义:

       单调队列是指一个队列内部的元素具有严格单调性的一种数据结构,分为单调递增队列和单调递减队列。

    性质:
       ① 单调队列必须满足从队头到队尾的严格单调性。
       ② 满足队列的先进先出特性,排在队列前面的比排在队列后面的要先出队。

    练习

       单调栈和单调队列可以用STL中的stack(栈)和deque(双端队列)实现,也可以手写数组实现并且因为数据只会进出至多一次,所以不会超限。

       单调栈&单调队列的思想和实现都比较简单,可以试做以下例题去体验这种思想。

    单调栈:

    poj 3250  Bad Hair Day

    #include<iostream>
    #include<cstdio>
    #include<stack>
    using namespace std;
    int const maxn=80005;
    long long h[maxn],sum;
    stack<long long> sta;
    int main()
    {
      int n,i;
      scanf("%d",&n);
      for(i=1;i<=n;i++) scanf("%lld",&h[i]);
      for(i=1;i<=n;i++)
      {
        while(!sta.empty()&&h[i]>=h[sta.top()]) sta.pop();
        sum+=sta.size();
        sta.push(i);
      }
      printf("%lld
    ",sum);
      return 0;
    }
    View Code

    poj 2796  Feel Good

    #include<iostream>
    #include<cstdio>
    #include<stack>
    using namespace std;
    int const maxn=100005;
    long long w[maxn],sum[maxn];
    int L[maxn],R[maxn];
    stack<long long> sta;
    int main()
    {
      int n,i,l,r;
      long long ans=-1;
      scanf("%d",&n);
      for(i=1;i<=n;i++) scanf("%lld",&w[i]),sum[i]=sum[i-1]+w[i];
      for(i=n;i>=1;i--)
      {
        while(!sta.empty()&&w[i]<w[sta.top()]) 
         L[sta.top()]=i+1,sta.pop();
        sta.push(i);
      }
      while(!sta.empty()) L[sta.top()]=1,sta.pop();
      for(i=1;i<=n;i++)
      {
        while(!sta.empty()&&w[i]<w[sta.top()]) 
         R[sta.top()]=i-1,sta.pop();
        sta.push(i);
      }
      while(!sta.empty()) R[sta.top()]=n,sta.pop();
      for(i=1;i<=n;i++)
      {
        if(ans<w[i]*(sum[R[i]]-sum[L[i]-1]))
         {
           l=L[i];
           r=R[i];
           ans=w[i]*(sum[R[i]]-sum[L[i]-1]);
         }
      }
      printf("%lld
    %d %d
    ",ans,l,r);
      return 0;
    }
    View Code

    poj 2559  Largest Rectangle in a Histogram

    #include<iostream>
    #include<cstdio>
    #include<stack>
    using namespace std;
    struct node
    {
      int w;
      long long h;
      node(){}
      node(int a,long long b)
      {w=a;h=b;}
    };
    int const maxn=100005;
    long long h[maxn];
    int main()
    {
      int n,i;
      long long ans;
      while(scanf("%d",&n)&&n)
      {
        stack<node> sta;
        ans=-1;h[n+1]=0;
        for(i=1;i<=n;i++) scanf("%lld",&h[i]);
        for(i=1;i<=n+1;i++)
        {
          if(sta.empty()||h[i]>sta.top().h) sta.push(node(1,h[i]));
          else
          {
            int t=0;
            while(!sta.empty()&&h[i]<=sta.top().h)
            {
             t+=sta.top().w;
             ans=max(ans,sta.top().h*t);
             sta.pop();
            }
            sta.push(node(t+1,h[i]));
          }
        }
        printf("%lld
    ",ans);
    }
      return 0;
    }
    View Code

    单调队列:

    hdu 3530  Subsequence

    #include<iostream>
    #include<cstdio>
    #include<queue>
    using namespace std;
    const int maxn=100010;
    deque <int> quemax,quemin;
    int w[maxn];
    int main()
    {
      int i,n,m,k,ans,cnt;
      while(~scanf("%d%d%d",&n,&m,&k))
      {
        quemax.clear();quemin.clear();ans=0;cnt=0;
        for(i=1;i<=n;i++) scanf("%d",&w[i]);
        for(i=1;i<=n;i++)
        {
          while(!quemax.empty()&&w[i]>w[quemax.back()]) quemax.pop_back();
          quemax.push_back(i);
          while(!quemin.empty()&&w[i]<w[quemin.back()]) quemin.pop_back();
          quemin.push_back(i);
          while(!quemax.empty()&&!quemin.empty()&&w[quemax.front()]-w[quemin.front()]>k)
          {
            if(quemax.front()<quemin.front())
             cnt=quemax.front(),quemax.pop_front();
            else
             cnt=quemin.front(),quemin.pop_front();
          }
          if(!quemax.empty()&&!quemin.empty()&&w[quemax.front()]-w[quemin.front()]>=m) ans=max(ans,i-cnt);
        }
        printf("%d
    ",ans);
      }
      return 0;
    }
    View Code

    poj 2823  Sliding Window

    #include<iostream>
    #include<cstdio>
    #include<queue>
    using namespace std;
    const int maxn=1000005;
    deque <int> quemax,quemin;
    int w[maxn],mmax[maxn],mmin[maxn];
    int main()
    {
      int i,n,k;
      while(~scanf("%d%d",&n,&k))
      {
        quemax.clear();quemin.clear();
        for(i=1;i<=n;i++) scanf("%d",&w[i]);
        for(i=1;i<=n;i++)
        {
          while(!quemax.empty()&&w[i]>w[quemax.back()]) quemax.pop_back();
          quemax.push_back(i);
          while(!quemax.empty()&&quemax.front()<=i-k) quemax.pop_front();
          mmax[i]=w[quemax.front()];
    
          while(!quemin.empty()&&w[i]<w[quemin.back()]) quemin.pop_back();
          quemin.push_back(i);
          while(!quemin.empty()&&quemin.front()<=i-k) quemin.pop_front();
          mmin[i]=w[quemin.front()];
        }
        for(i=k;i<=n;i++)
         printf("%d%c",mmin[i],i==n?'
    ':' ');
        for(i=k;i<=n;i++)
         printf("%d%c",mmax[i],i==n?'
    ':' ');
      }
      return 0;
    }
    View Code

    洛谷 P2032  扫描

    #include<iostream>
    #include<cstdio>
    #include<queue>
    using namespace std;
    int const maxn=2*1e6+5;
    int w[maxn],mmax[maxn];
    deque<int> que;
    int main()
    {
      int i,n,k;
      scanf("%d%d",&n,&k);
      for(i=1;i<=n;i++) scanf("%d",&w[i]);
      for(i=1;i<=n;i++)
      {
        while(!que.empty()&&que.front()<=i-k) que.pop_front();
        while(!que.empty()&&w[i]>w[que.back()]) que.pop_back();
        que.push_back(i);
        mmax[i]=w[que.front()];
      }
      for(i=k;i<=n;i++) printf("%d
    ",mmax[i]);
      return 0;
    }
    View Code

    洛谷 P1714  切蛋糕

    #include<bits/stdc++.h>
    using namespace std;
    int const maxn=500005;
    int sum[maxn];
    deque<int> que;
    int main()
    {
      int n,m,x,i,ans=-1;
      scanf("%d%d",&n,&m);
      for(i=1;i<=n;i++) scanf("%d",&x),sum[i]+=sum[i-1]+x;
      for(i=1;i<=n;i++)
      {
        while(!que.empty()&&que.front()<i-m) que.pop_front(); 
        while(!que.empty()&&sum[i]<sum[que.back()]) que.pop_back();
        que.push_back(i);
        ans=max(ans,sum[i]-sum[que.front()]);
      }
      printf("%d
    ",ans);
      return 0;
    }
    View Code

    洛谷 P2947  Look Up

    #include<bits/stdc++.h>
    using namespace std;
    int const maxn=100005;
    int h[maxn],ans[maxn];
    stack<int> sta;
    int main()
    {
      int n,i;
      scanf("%d",&n);
      for(i=1;i<=n;i++) scanf("%d",&h[i]);
      for(i=1;i<=n;i++)
      {
        while(!sta.empty()&&h[i]>h[sta.top()])
        {
          ans[sta.top()]=i;
          sta.pop();
        }
        sta.push(i);
      }
      while(!sta.empty()) ans[sta.top()]=0,sta.pop();
      for(i=1;i<=n;i++) printf("%d
    ",ans[i]);
      return 0;
    }
    View Code
    本博客仅为本人学习,总结,归纳,交流所用,若文章中存在错误或有不当之处,十分抱歉,劳烦指出,不胜感激!!!
  • 相关阅读:
    Ubuntu下MySQL
    submit踩的坑
    转发,重定向以及区别和简单的session对象(转)
    Markdown链接打开新页面而非本页面跳转,补:target属性
    登录失败使用session传数据
    git安装连接码云提交
    Markdown的超链接由新窗口打开
    GitHub搜索相关项目
    mysql安装
    jdk的安装和配置
  • 原文地址:https://www.cnblogs.com/VividBinGo/p/11384066.html
Copyright © 2011-2022 走看看