求取:以某矩形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; }