思路
两题题目类似,都要求出最大矩形,可以用单调栈来处理,小于栈顶元素就不断出栈,保证栈是递增的。
定义左界和右界表示以当前元素为最高高度的连续矩形区域的左边界和右边界
在出栈时,会更新被出栈元素的右界,同时一个元素的左界在入栈前就已经确定。
POJ 2559
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<b;i++)
#define debug(a) printf("a =: %d\n",a);
const int INF=0x3f3f3f3f;
const int maxn=1e5+50;
const int Mod=1000000007;
const double PI=acos(-1);
typedef long long ll;
using namespace std;
struct Node{
int h,startPos;
Node(){}
Node(int startPos,int h){
this->h=h;
this->startPos=startPos;
}
bool operator<(const Node &r)const{
return h<r.h;
}
};
int n;
int h[maxn];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
while(~scanf("%d",&n) && n){
for(int i=1;i<=n;i++) {
scanf("%d",&h[i]);
}
ll ans=0;
stack<Node> st;
st.push(Node(0,-1));
for(int i=1;i<=n+1;i++){
int height,curPos;
if (i>n) height=0;
else height=h[i];
curPos=i;
Node tmp=Node(curPos,height);
while(height<st.top().h){
tmp=st.top();
st.pop();
ans=max(ans,(ll)(curPos-tmp.startPos)*tmp.h);
}
st.push(Node(tmp.startPos,height));
}
cout<<ans<<'\n';
}
return 0;
}
POJ 2796
这题的左界和右界确定明显一些(上题没有显式写出)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<b;i++)
#define debug(a) printf("a =: %d\n",a);
const int INF=0x3f3f3f3f;
const int maxn=1e5+50;
const int Mod=1000000007;
const double PI=acos(-1);
typedef long long ll;
using namespace std;
struct Node{
int h,startPos,id;
Node(){}
Node(int startPos,int h,int id){
this->h=h;
this->startPos=startPos;
this->id=id;
}
bool operator<(const Node &r)const{
return h<r.h;
}
};
int n;
int h[maxn];
int l[maxn],r[maxn];
ll sum[maxn];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
while(~scanf("%d",&n) && n){
sum[0]=0;
for(int i=1;i<=n;i++) {
scanf("%d",&h[i]);
sum[i]=sum[i-1]+h[i];
}
ll ans=0;
stack<Node> st;
st.push(Node(0,-1,0));
for(int i=1;i<=n+1;i++){
int height,curPos;
if (i>n) height=0;
else height=h[i];
curPos=i;
Node tmp=Node(curPos,height,i);
while(height<st.top().h){
tmp=st.top();
st.pop();
r[tmp.id]=curPos-1;
// ll curAns=(ll)(sum[curPos-1]-sum[tmp.startPos-1])*tmp.h;
// ans=max(ans,curAns);
}
l[i]=tmp.startPos;
st.push(Node(tmp.startPos,height,i));
}
int ansL=1,ansR=1; //trick
for(int i=1;i<=n;i++){
// printf("%d %d %d\n",i,l[i],r[i]);
ll tmp=(sum[r[i]]-sum[l[i]-1])*h[i];
if (tmp>ans){
ans=tmp;
ansL=l[i];
ansR=r[i];
}
}
printf("%lld\n%d %d\n",ans,ansL,ansR);
}
return 0;
}
/*
1
0
3
1 2 1
4
1 2 2 1
9
1 1 1 1 1 1 1 2 2
10
102 58 149 52 66 52 105 28 161 111
6
97 111 154 93 72 109
16
1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1
ans:
0
1 1
4
1 3
8
2 3
11
1 9
30368
1 7
45792
1 6
17
1 16
*/