单调栈 HDU - 1506 POJ - 3250 POJ - 2796

单调栈
单调栈的性质从字面意思上就是利用其单调性对元素进行入栈与出栈的操作的过程来达到所需的要求。
因为其进行整个操作过程中只有出栈与入栈所以时间是O(n)。
题目集:https://www.csdn.net/.
(如果您用的是移动网那么请将net 改成 z180.cn 我也不知为什么)
单调栈例题:
<1> HDU - 1506:

直方图是由在共同基线上排列的矩形序列组成的多边形。矩形具有相等的宽度,
但可以具有不同的高度。请在直方图中计算最大矩形的面积,该直方图也是在
公共基线上对齐的。
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stack>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
#define MM(a,b) memset(a,b,sizeof(a))
ll a[N],l[N],r[N],ans=-1;
int main()
{
    int n;
    while(cin >> n ){
        MM(a,0);
        ans=-1;
        if(n == 0) break;
        for(int i = 0 ; i < n ; i++){
            cin >> a[i];
        }
        stack<ll> s;
        for(int i = 0 ; i < n ; i++){
            while(!s.empty() && a[i]<= a[s.top()])
                s.pop();
            l[i]=s.empty()?0:s.top()+1;
            s.push(i);
        }
        stack<ll> ss;
        for(int i = n-1 ; i >=0 ; i--){
            while(!ss.empty() && a[i] <= a[ss.top()])
                ss.pop();
            r[i]=ss.empty()==1?n-1:ss.top()-1;
            ss.push(i);
        }
        for(int i = 0 ; i < n ; i++){
           ans=max(ans,a[i]*(r[i]-l[i]+1));
        }
        cout << ans << endl;
    }
}

<2>POJ - 3250

Farmer John的奶牛在风中凌乱了它们的发型……
每只奶牛都有一个身高hi(1 ≤ hi ≤ 1,000,000,000),现在在这里有一排全部
面向右方的奶牛,一共有N只(1 ≤ N ≤ 80,000)。对于奶牛i来说,
如果奶牛i+1,i+2,……,N这些奶牛的身高严格小于奶牛i,则奶牛i可以
看到它们凌乱的发型。
令ci表示第i只奶牛能够看到的发型数量,请计算c1 + c2 + c3 + … + cN的值
#include <iostream>
#include <stack>
using namespace std;
const int N = 8e4+10;
typedef long long ll;
ll a[N],ans=0;
int main()
{
    int n,x;
    cin >> n;
    for(int i = 0 ; i < n ; i++){
        cin >> a[i];
    }
    stack<int> s;
    for(int i = n-1 ; i >= 0 ; i--){
        while(s.size() && a[s.top()] < a[i]){
            s.pop();
        }
        x = s.empty()?n-1:s.top()-1;
        ans += 1ll*(x-i);
        s.push(i);
    }
    cout << ans;
    return 0;
}

<3>POJ - 2796

给定n天,每一天有一个非负权值ai。某一段时间[l, r]的权值被定义为
即时间内的每天的权值和乘以这段时间内的最小权值。
求一个时间段,使这个时间段的权值最大。
#include <iostream>
#include <stack>
#include <stdio.h>
using namespace std;
const int N = 1e5+10;
typedef long long ll;
ll l[N],r[N],ans=-1,tem,a[N],sum[N],lef=0,rig=0;
int main()
{
    int n;
    sum[0]=0;
    scanf("%d",&n);
    for(int i = 1 ; i <= n ; i++){
        scanf("%lld",&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    stack<int> s;
    for(int i = 1 ; i <= n ; i++){
        while(s.size() && a[s.top()] >= a[i]){
            s.pop();
        }
        l[i] = s.empty()?1:s.top()+1;
        s.push(i);
    }
    while(s.size()) s.pop();
    for(int i = n ; i >= 1 ; i--){
        while(s.size() && a[i] <= a[s.top()]){
            s.pop();
        }
        r[i] = s.empty()?n:s.top()-1;
        s.push(i);
    }
    for(int i = 1 ; i <= n ; i++){
        tem = a[i]*(sum[r[i]]-sum[l[i]-1]);
        if(tem > ans){
            lef=l[i];
            rig=r[i];
            ans=tem;
        }
    }
    cout << ans << endl << lef << " " << rig << endl;
    return 0;
}

所以在写了三道题之后感觉单调栈的基本模板是

stack<int> s;
for(int i = 1 ; i <= n ; i++){
        while(s.size() && a[s.top()] ?  a[i]){
            s.pop();
        }
        这里是可以添加标记的条件
        s.push(i);这个很关键,每一步的最后都要让元素入栈不然就没有元素了。
    }
    总之要记住入栈与出栈是每个元素都要经历的
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值