单调栈(学习笔记)

单调栈原理与单调队列类似,就是队列与栈的差别.(感觉单调队列的应用比单调栈更广)

单调栈:求最大矩形面积

如图所示,在一条水平线上有n个宽为1的矩形,求包含于这些矩形的最大子矩形面积(图中的阴影部分的面积即所求答案)。

根据单调队列的思想,建立一个栈,用来保存若干个矩形,这些矩形的高度是单调递增的.从左到右依次扫描每个矩形:

1 如果当前矩形比栈顶矩形高,直接进栈

2 否则,不断把栈内比当前矩形高的的矩形出栈,直到栈为空或者栈顶矩形的高度比当前矩形小.在出栈过程中,累计被弹出的矩形的宽度之和,并且每弹出一个矩形,就用该矩形的高度乘上以经累计的宽度去更新答案max.整个出栈过程结束后,把高度为当前扫描到的矩形高度,宽度为累计宽度的新矩形入栈.

3 整个扫描结束后,还要计算栈内剩余矩形能够构成的最大矩形面积,方法跟步骤2类似.

第2步看文字不理解的话,建议手画几个高矮不齐的矩形根据代码模拟一下,一定要弄懂,这是单调栈的核心思想.

while(~scanf("%d",&n)){
    if(!n)break;
    int top=0;
//模拟栈顶指针
    long long ans=0;
//记录最大面积ans
    for(int i=1;i<=n;i++)h[i]=read();
//读入每个矩形的高度
    h[n+1]=0;
//这是一个为了实现第3步的小技巧
    for(int i=1;i<=n+1;i++){
        if(h[i]>=st[top]){
            top++;
            st[top]=h[i];
            wid[top]=1;
        }
//如果当前扫描到的矩形的高度比栈顶矩形高度大
//直接把当前矩形入栈,同时该矩形宽度设为1
        else{
            int width=0;
            while(st[top]>h[i]){
                width+=wid[top];
//累计出栈矩形高度
                ans=max(ans,(long long)width*st[top]);
//同时把该出栈矩形的高度乘累计宽度以更新最大值
                top--;
            }
            st[++top]=h[i];
            wid[top]=width+1;
//把高度为当前扫描到的矩形的高度
//宽度为累计宽度的新矩形入栈
        }
    }
    printf("%lld\n",ans);
}

猜你喜欢

转载自www.cnblogs.com/PPXppx/p/10324308.html