题意:
题意:给你宽度为一,高度不同的n个矩形,让求出一个最大面积的矩形。
如下图所示
分析:
方法一:
根据题意可知,若以h为起点,分别往两边找比h矮的矩形,此时比h矮的前一个组成的矩形便是能围成的最大面积;
上述有一些意识流,看代码比较好理解
#include <iostream>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include <cstring>
#include <stack>
#include <string>
using namespace std;
typedef long long ll;
const int N = 1e5+199;
const double Pi = acos(-1);
ll h[N];
int l_min[N],r_min[N];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&h[i]);
l_min[i]=r_min[i]=i;
}
h[0]=h[n+1]=-1;
for(int i=1;i<=n;i++){//看似是n^2的复杂度,其实是O(n),有点KMP的意思
int j=i-1;
while(h[j]>=h[i])//找i的左边比自己第一个矮的位置
j=l_min[j]-1;//这一步很重要,可以快速收敛,这样就不是n^2的复杂度了
l_min[i]=j+1;
}
for(int i=n;i>=1;i--){
int j=i+1;
while(h[j]>=h[i])//找i的右边比自己第一个矮的位置
j=r_min[j]+1;
r_min[i]=j-1;
}
ll ans=0;
for(int i=1;i<=n;i++){
ans=max(ans,(ll)(r_min[i]-l_min[i]+1)*h[i]);
}
printf("%lld\n",ans);
return 0;
}
方法二:单调栈
我们用栈来维护一个单调递增的矩形高度,如果遇到一个大于等于栈顶的元素,便将其入栈,否则弹出,然后计算,直到栈顶元素小于当前的元素才再次入栈;
同样有点意识流,还是看代码,最后能手动模拟一下;
#include <iostream>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include <cstring>
#include <stack>
#include <string>
using namespace std;
typedef long long ll;
const int N = 1e5+199;
const double Pi = acos(-1);
ll h[N];
int main()
{
// #ifndef ONLINE_JUDGE
// freopen("in.txt","r",stdin);
// #endif // ONLINE_JUDGE
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%lld",&h[i]);
}
h[n]=-1;//这是要用到单调栈必不可少的
int pos=0;
ll ans=0,maxval=0;
stack<int>s;//用栈来存储下标
while(pos<=n){
if(s.empty() || h[pos]>=h[s.top()])
s.push(pos);
else{
int k;
while(!s.empty() && h[pos]<h[s.top()]){
k=s.top();
s.pop();
ans=max(ans,h[k]*(pos-k));
}
h[k]=h[pos];//这个地方需要好好理解
s.push(k);
}
pos++;
}
printf("%lld\n",ans);
return 0;
}