http://poj.org/problem?id=2559
题目大意:一堆宽为1 高可变的矩形凑在一起 求最大矩形是多大
思路 单调栈 用两次 从左到右 和从右到左 求出每个矩形的左右最长延伸度
最后再过一遍 求出最大面积即可 2 1 5 6 1 3 3为例 我们画一下栈 帮助理解这个题。编号分别是1 2 3 4 5 6 7
一开始
2 入栈 第一块左为0 栈为1
1入栈 第二块左为0 栈为2
5 入栈 第三块左为2 栈为2 3
6 入栈 第四块左为3 栈为2 3 4
1 入栈 第五块左为0 栈为5
3 入栈 第六块左为5 栈为5 6
3 入栈 第七块左为5 栈为5 7
之后我们在倒着从后往前找右边的边界
3 入栈 第七块 右为8 栈为7
3 入栈 第六块 右为8 栈为6
1 入栈 第五块 右为8 栈为5
6 入栈 第四块 右为5 栈为5 4
5 入栈 第三块 右为5 栈为5 3
1 入栈 第二块 右为8 栈为2
2 入栈 第一块 右为2 栈为1
根据以上两图可以计算出每个矩形的最大面积为
2 7 8 5 7 6 6
#include <algorithm> #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <queue> #include <stack> #include <unordered_map> #include <vector> using namespace std; typedef long long ll; const int maxn = 1e5 + 5; int arr[maxn], l[maxn], r[maxn]; int main() { int n; ll ans = 0; stack<int> st; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &arr[i]); } for(int i = 0; i < n; i++) //寻找每个矩形的左边界 保证严格递增 { while (!st.empty() && arr[st.top()] >= arr[i]) //非空且新的值小于等于当前栈顶的值 { st.pop(); } if (st.empty()) l[i] = 0; else l[i] = st.top()+1; st.push(i); } while (!st.empty()) { st.pop(); } for (int i = n - 1; i >= 0; i--)//找右边 { while (!st.empty() && arr[st.top()] >= arr[i]) st.pop(); if (st.empty()) r[i] = n; else r[i] = st.top(); st.push(i); } for (int i = 0; i < n;i++){ //cout << r[i] << ' ' << l[i] << endl; //cout << (ll)arr[i] * (r[i] - l[i]) << endl; ans = max(ans, (ll)arr[i] * (r[i] - l[i])); } cout << ans << endl; return 0; }
Comments | NOTHING