ACM单调栈

单调栈指的是一个栈,栈内的元素是单调的。

单调递增栈:从栈底到栈顶元素依次从大到小

单调递减栈:从栈底到栈顶元素依次从小到大

建立一个单调栈

例:如果要维护一个递增单调栈(也就是栈顶的元素最小),那么元素要入栈时,如果为空栈或者栈顶元素比入栈元素大,就入栈,否则就依次将栈顶元素出栈,直到满足条件。

伪代码:

stack<int> s1;
//一般需要在数组中添加一个结束标识符
    for(遍历数组){
        if(栈为空||栈顶元素大于当前元素){
            入栈;
        }else{
            while(栈不为空&&栈顶元素小于当前元素){
                栈顶元素出栈;
                更新结果;
            }
            当前元素入栈;
        }
    }

应用

1.视野总和:

有n个人在排队,他们身高各不相同,都向右看,能看到比自己个子矮的人的头顶,直到下一个比自己更高的人。

在这里插入图片描述

**输入:n个数表示n个人的身高输出:**所有人能看到的头顶总和

例:输入: 4 3 7 1
输出:2
(个子为4的人能看见个子为3的人,7能看见1)

思路:本质就是找到下一个比自己个子高的人,然后计算相隔的距离(也就是中间有几个人),再加和。
可以通过构建单调递增栈来解决。当遇到下一个比自己高的人时就开始处理数据。

const int INT_INF = 0x3F3F3F3F;
int fieldSum(vector<int>& v){
    v.push_back(INT_INF);
    stack<int> st;
    int sum = 0;
    for(int i = 0;i<v.size();i++){
        if(st.empty() || v[i]<st.top()){//如果空栈或者将要入栈的元素更小
            st.push(v[i]);
        }else {
            while(!(st.empty() || v[i]<st.top())){
                int top = st.top();
                st.pop();
                sum += (i - top - 1);//处理数据
            }
            st.push(v[i]);
        }
    }
    return sum;
}

2.柱形图中的最大矩形面积

链接:https://ac.nowcoder.com/acm/contest/22669/Q

柱状图是有一些宽度相等的矩形下端对齐以后横向排列的图形,但是小A的柱状图却不是一个规范的柱状图,它的每个矩形下端的宽度可以是不相同的一些整数,分别为a[i]a[i]a[i],每个矩形的高度是h[i]h[i]h[i],现在小A只想知道,在这个图形里面包含的最大矩形面积是多少

输入描述:

一行一个整数N,表示长方形的个数
接下来一行N个整数表示每个长方形的宽度
接下来一行N个整数表示每个长方形的高度

输出描述:

一行一个整数,表示最大的矩形面积

输入

7
1 1 1 1 1 1 1
2 1 4 5 1 3 3

输出

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;//pair int int(pii)
typedef long long int ll;
const int INF = 0x3f3f3f3f;//无限大
ll maxSqu(vector<pii> vec){
    vec.push_back(make_pair(-1*INF,0));//在数组最后插入一个结束标识符,保证运行的时候能处理掉所有的数据
    stack<pii> st;
    ll max = -1*INF;//存储结果
    for(int i  = 0;i<vec.size();i++){//遍历数组
        if(st.empty() || st.top().first<= vec[i].first){//如果符合条件就入栈
            st.push(vec[i]);
        }else{//不符合条件就依次出栈直到可以入栈
            int wid = 0;//用来表示现在宽度是多少
            while(!st.empty() && st.top().first > vec[i].first){//出栈
                pii top = st.top();
                st.pop();
                wid+=top.second;
                ll res = ll(wid)*top.first;
                max = max>res?max:res;
            }
            //下面这两行很关键,用来实现向左拓展矩形(通过将栈顶元素的宽度改成它以及它左边比它高的矩形的宽度的和)
            st.push(vec[i]);
            st.top().second += wid;
        }
    }
    return max;
}
int main(){
    int n;
    cin>>n;
    vector<pii> v(n);
    for(int i = 0;i<n;i++){
        cin>>v[i].second;
    }
    for(int i = 0;i<n;i++){
        cin>>v[i].first;
    }
    cout<<maxSqu(v);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值