51nod 1102 面积最大的矩形

题目地址在这儿

求取:以某矩形g[i]为最小值的区间的左右端点,得到一个临时解。所有临时解中的最大值即为解。

求取区间的方法可以用单调栈,也可以用下面这种十分简洁的类似于递归的方法。下面这种解法求出来的区间是开区间,也正是因为开区间,所以跳转很方便。

L[i]是以第i根柱子为最小值的左开区间点。若g[i] <= g[L[i]],则L[i]=L[L[i]];

打个比方,柱子高度为1,3,9,7,5。g[4]=7,一开始L[4]初始化为3,那么若g[4]<=g[L[4]],即7=g[4]<=g[3]=9,那么L[4]=L[L[4]]=L[3]=2。

#include <stdio.h>
#include <iostream>
using namespace std;

#define ll long long
const int maxN=1e5+5;
ll N, L[maxN], R[maxN], g[maxN];

int main() {
#ifndef ONLINE_JUDGE
    freopen("data.in", "r", stdin);
#endif
    scanf("%lld", &N);
    for (int i = 1; i <= N; ++i)
        scanf("%lld", &g[i]);
    for (int i = 1; i <= N; ++i) {
        L[i] = i - 1;
        R[i] = i + 1;
    }
    for (int i = 1; i <= N; ++i)
        while (L[i] && g[L[i]] >= g[i]) L[i] = L[L[i]];
    for (int i = N; i >= 1; --i)
        while (R[i] <= N && g[R[i]] >= g[i]) R[i] = R[R[i]];

    ll ans = 0;
    for (int i = 1; i <= N; ++i)
        ans = max(ans, g[i] * (R[i] - L[i] - 1));
    printf("%lld
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/Rosebud/p/9518980.html