单调栈基础题

                                         单调栈

这几天在完成寒假作业的时候,了解到了单调栈和单调队列的使用,以及作用。
单调栈:单调性,强调单调。栈里的元素符合增或减。概念很简单。

刚开始接触单调栈的时候,看别人代码模模糊糊,不是很懂。我写单调栈都是用数组模拟,定义一个s[maxn]数组,s数组就是用来记录栈顶坐标。
下面我们来看看单调栈的基础题。

Bad Hair Day  POJ 3250
Feel Good   POJ 2796
Largest Rectangle in a Histogram   POJ 2559 HDU 1506
这里有三个很基础的题目,适合我们这种刚接触单调栈的初学者。
下面附上自己的AC代码

/*   POJ 3250 */

#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<queue>
#include<vector>
#include<stack>
#include<list>
#include<map>
#include<set>
using namespace std;
typedef unsigned long long llu;
const int maxn = 80000 + 5;
llu stc[maxn];
int main()
{
    llu n,ans=0,x;
    long long top=-1;
    scanf("%llu",&n);
    while(n--)
    {
        scanf("%llu",&x);
        while(top>=0&&x>=stc[top]) top--;//维护一个单调递减的栈 如果大于栈顶元素 栈顶出站
        stc[++top]=x;//新元素 入栈
        ans+=top;
    }
    printf("%llu\n",ans);
}


/*   POJ 2796 */

#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<queue>
#include<vector>
#include<stack>
#include<list>
#include<map>
#include<set>
using namespace std;
#define manx maxn
const int maxn = 100000 + 5;
int l[manx],r[maxn],stc[maxn];
long long a[maxn],sum[manx];
int main()
{
    int n,i;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        sum[i]=sum[i-1]+a[i];//前缀和
        l[i]=r[i]=i;
    }
    int top=0;
    for(i=1;i<=n+1;i++)//注意n+1  因为下面r[stc[top]]=i-1;  
    {
        while(top&&a[i]<=a[stc[top]])//维护单调递增栈
        {
            r[stc[top]]=i-1;//确定右区间坐标 
            top--;
        }
        l[i]=stc[top];//确定左区间坐标
        stc[++top]=i;
    }
    long long temp,ans=-1,ans1=0,ans2=0;
    for(i=1;i<=n;i++)
    {
        temp=(sum[r[i]]-sum[l[i]])*a[i];//枚举每个区间的值
        if(temp>=ans)
        {
            ans=temp;
            ans1=l[i];
            ans2=r[i];
        }
    }
    printf("%lld\n%lld %lld",ans,ans1+1,ans2);

}


/*   POJ 2559 || HDU 1506 */

#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<queue>
#include<vector>
#include<stack>
#include<list>
#include<map>
#include<set>
const int MAXN = 100000 +10;
using namespace std;
int l[MAXN],r[MAXN],s[MAXN];
int main()
{
    long long a[MAXN];
    int n;
    int top;
    while(scanf("%d",&n),n)
    {
        long long ans=0;
        for(int i=1; i<=n; i++)
        {
            scanf("%lld",&a[i]);
            l[i]=r[i]=i;
        }
        top=0;
        for(int i=1; i<=n; i++)//确定左坐标 就是i点左边的 低或者等于这个矩形的位置
        {
            while(top&&a[i]<=a[s[top]])//每次我们加入一个点 和这个区间最小的点比较(及栈顶元素)
                top--;
            if(top==0)//栈空
                l[i]=1;
            else l[i]=s[top]+1;
            s[++top]=i;
        }
        top=0;
        for(int i=n; i>=1; i--)//确定右坐标  同上
        {
            while(top&&a[i]<=a[s[top]])//维护一个递增栈
                top--;
            if(top==0)//栈空
                r[i]=n;
            else r[i]=s[top]-1;
            s[++top]=i;
        }
        //for(int i=1;i<=n;i++)
            //cout<<l[i]<<"    "<<r[i]<<"****"<<endl; //可以看相应点的坐标l[i]是记录 i点左边最小的点坐标(含等于) r[i]是最大的(含等于)
        for(int i=1; i<=n; i++)
        {
            long long temp=a[i]*(r[i]-l[i]+1);//枚举每个区间的值
            if(temp>ans)
                ans=temp;
        }
        cout<<ans<<endl;
    }
}
最后一个题画图辅助理解更好。总之强调一个单调性,单调栈不同普通枚举 时间得到了优化。当然是用STLstack也是可以的,只是比数组模拟的速度慢。
过一阵子,熟悉了DP题 在来更新单调队列优化DP吧,现在看到DP头就大  


<think>好的,用户想查询C++标准库中是否有内置的单调栈功能函数。首先,我需要回忆C++标准库的内容。已知STL提供了多种容器和算法,比如vector、queue、stack等,还有像优先队列(priority_queue)这样的适配器。但单调栈并不是一个直接提供的容器。 接下来,我需要确认用户提到的单调栈是什么。单调栈是一种数据结构,通常用于维护元素的单调性,常用于解决特定算法问,比如找到下一个更大元素或最大矩形面积等。根据引用[4],用户可能是在处理类似的问,比如矩阵中的最大值最小值枚举,需要用到单调队列或单调栈。 现在检查C++的标准库文档,确认是否有名为monotonic_stack的容器或相关函数。根据我的知识,C++标准库中并没有内置的单调栈实现。用户需要自己基于现有的容器(如std::stack)来实现单调栈的逻辑。例如,可以通过在每次插入元素时维护栈的单调性,手动弹出破坏单调性的元素。 然后,参考引用[4]中的内容,用户可能在处理二维问时需要用到单调结构,但标准库并没有直接支持。因此,回答应指出C++没有内置的单调栈,但提供手动实现的示例代码,并说明其应用场景。 此外,用户可能对性能优化感兴趣,比如使用emplace()来提高效率,如引用[3]提到的,避免不必要的复制操作。在示例代码中使用emplace_back可能更高效。 最后,生成相关问,帮助用户深入理解如何实现和应用单调栈,以及相关数据结构如单调队列和优先队列的区别。</think>C++标准库中目前没有直接提供名为"单调栈"的预封装容器或专用函数,但可以通过组合现有容器实现其功能。以下是实现方法和应用建议: ### 实现方法 1. **基础实现**:使用$std::stack$容器配合自定义逻辑维护单调性 ```cpp #include <stack> #include <vector> template<typename T> class MonotonicStack { private: std::stack<T> st; bool increasing; // true为递增栈,false为递减栈 public: MonotonicStack(bool inc = true) : increasing(inc) {} void push(const T& val) { while (!st.empty() && (increasing ? (val < st.top()) : (val > st.top()))) { st.pop(); } st.push(val); } // 其他必要成员函数... }; ``` 2. **数组实现**:更高效的方式使用$std::vector$模拟栈 ```cpp std::vector<int> mono_stack; for (int num : nums) { while (!mono_stack.empty() && num > mono_stack.back()) { mono_stack.pop_back(); } mono_stack.emplace_back(num); // 使用emplace避免复制操作[^3] } ``` ### 典型应用场景 1. **下一个更大元素**:$O(n)$时间复杂度解决Leetcode 496 2. **直方图最大矩形**:结合高度计算(Leetcode 84) 3. **滑动窗口最大值**:可通过单调队列实现(相关实现见引用[4]) ### 性能建议 - 优先使用$std::vector$代替$std::stack$,因其内存连续且支持随机访问 - 使用$emplace_back()$替代$push()$避免元素复制[^3] - 预分配容量:$reserve()$方法减少动态扩容开销
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值