单调栈裸题
如果矩形高度从左到右是依次递增,那我们枚举每个矩形高度,宽度拉到最优,计算最大面积即可
当有某个矩形比前一个矩形要矮的时候,这块面积的高度就不能大于他本身,所以之前的所有高于他的矩形多出来的部分都没用了,不会再计算第二次。
因此我们只需要用单调栈维护矩形高度即可,当有高度较低的矩形进栈时,先将之前比他高的每个矩形弹出,宽度累加,更新答案。然后我们要进栈的矩形的宽度也要变成之前累加的宽度+1,因为要保留有用部分。。
有个小技巧:为了方便程序,在末尾加一个高度为0的矩形
#include#define INF 0x3f3f3f3fusing namespace std;typedef long long ll;inline int lowbit(int x){ return x & (-x); }inline int read(){ int X = 0, w = 0; char ch = 0; while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); } while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar(); return w ? -X : X;}inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }inline int lcm(int a, int b){ return a / gcd(a, b) * b; }template inline T max(T x, T y, T z){ return max(max(x, y), z); }template inline T min(T x, T y, T z){ return min(min(x, y), z); }template inline A fpow(A x, B p, C yql){ A ans = 1; for(; p; p >>= 1, x = 1LL * x * x % yql)if(p & 1)ans = 1LL * x * ans % yql; return ans;}ll h[100005], s[100005], w[100005], tot;int main(){ int n; while(cin >> n && n){ memset(h, 0, sizeof h); memset(s, 0, sizeof s); memset(w, 0, sizeof w); ll ans = 0; w[n + 1] = 0; tot = 0; for(int i = 1; i <= n; i ++) cin >> h[i]; for(int i = 1; i <= n + 1; i ++){ if(s[tot] > h[i]){ ll width = 0; while(tot > 0 && s[tot] > h[i]){ width += w[tot]; ans = max(ans, (ll)width * s[tot]); tot --; } s[++tot] = h[i], w[tot] = width + 1; } else{ s[++tot] = h[i], w[tot] = 1; } } printf("%lld\n", ans); } return 0;}