单调栈-19王祥力

单调栈,是栈内元素保持一定单调性(单调递增或单调递减)的栈。这里的单调递增或递减是指的从栈顶到栈底单调递增或递减。既然是栈,就满足后进先出的特点。与之相对应的是单调队列。
单调栈目的并不在于存储所有入栈元素。
对于一个单调递增栈,如果栈为空或入栈元素值小于栈顶元素值,则入栈;
否则,如果入栈则会破坏栈的单调性,则需要把比入栈元素小的元素全部出栈。
单调递减栈反之同理。
及时排除不可能的选项,保持策略集合的高度有效性和秩序性。
时间复杂度 O(n)O(n)。
举个栗子:
例如实现一个单调递减的栈,比如现在有一组数10,7,6,18。从左到右依次入栈,则如果栈为空或入栈元素值小于栈顶元素值,则入栈;否则,如果入栈则会破坏栈的单调性,则需要把比入栈元素小的元素全部出栈。单调递减的栈反之。
比如刚刚开始时栈为空,输入10,直接入栈,栈内元素为10.
7入栈时,栈顶元素10比7大,则7入栈,栈内元素为10,7.
6入栈时,栈顶元素7比6大,则6入栈,栈内元素为10,7,6.
18入栈时,栈顶元素6比12小,6出栈,此时栈顶元素为7,仍比18小,栈顶元素7继续出栈,此时栈顶元素为10,仍比18小,10出栈,此时栈为空,18入栈,栈内元素为18。
这就是单调栈的基本思想。
应用:
1.最基础的应用就是给定一组数,针对每个数,寻找它和它右边第一个比它大的数之间有多少个数。

2.给定一序列,寻找某一子序列,使得子序列中的最小值乘以子序列的长度最大。

3.给定一序列,寻找某一子序列,使得子序列中的最小值乘以子序列所有元素和最大。
其实实现代码有很多。
#include
#include
#include
#define ll long long
ll max(ll b,ll c)
{
return(b>c?b:c);
}

ll n,p;
ll a[100010]={0};
ll h[100010]={0},w[100010]={0};
ll ans;
int main()
{

while(scanf("%d",&n)&&n)
{
    ans=0; p=0;
    ll i;
    for( i=1;i<=n;i++) scanf("%d",&a[i]);
    a[n+1]=0;
    for(i=1;i<=n+1;i++)
    {
        if(a[i]>h[p]) h[++p]=a[i],w[p]=1;
        else{
            ll t=0;
            while(h[p]>a[i])
            {
                t+=w[p];
                ans=max(ans,t*h[p]);
                p--;
            }
            h[++p]=a[i],w[p]=t+1;
        }
    }
   printf("%lld\n",ans);
}

}

你可能感兴趣的:(单调栈-19王祥力)