单调栈

本题要求找出最大矩形的面积。从基本概念入手,给定长(本题也可以说“高”)和宽便可以确定一个矩形的面积,所以我们的任务便是找到高和宽。

首先,要尝试所有的区间很显然是不可能的;可以发现对于每一段区间,矩形的宽都可以用a数组的前缀和求出来,所以我们的任务重心转移到了矩形的高上。

求高便是求一段区间内h的最小值,这里容易想到单调队列栈。很显然此处不能用单调队列处理,因为并没有指定矩形的宽占多少区间,所以采用单调栈处理。
单调栈:求数组某个位置的值在哪个最大区间(相邻)是最值。
此时只要找到每个位置的在哪个最大区间是最小值即可,因为一旦超过这个区间,要么是超过了边界,要么是存在一个h[i]小于该高,此时高发生了改变。

最后简单概括:该方法是在每个h[i]都为高时,找到其对应的最大的宽,即可找到最大面积。

代码:

#include <iostream>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cctype>
#include <functional>
#include <string>
#include <cstring>
#include <sstream>
#include <deque>
#define fir first
#define sec second
using namespace std;

typedef long long ll;
typedef pair<int,int> P;
typedef pair<P,int> Q;

const int inf1=2e9+9;
const ll inf2=8e18+9;
const ll mol=1e9+7;
const int maxn=1e6+9;
const ll maxx=1e12+9;

int n,a[maxn],h[maxn];
int sum[maxn];
stack<int> st;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
    for(int i=1;i<=n;i++) scanf("%d",&h[i]);
    ll ans=0;
    st.push(0);
    for(int i=1;i<=n;i++)
    {
        while(h[i]<h[st.top()])
        {
            int H=h[st.top()]; st.pop();
            ans=max(ans,1ll*(sum[i-1]-sum[st.top()])*H);
        }
        st.push(i);
    }
    while(st.size()>1)
    {
        int H=h[st.top()]; st.pop();
        ans=max(ans,1ll*(sum[n]-sum[st.top()])*H);
    }
    printf("%lld\n",ans);
}