(POJ 2559)Largest Rectangle in a Histogram (POJ 2796) Feel Good(DP、单调栈)

思路

两题题目类似,都要求出最大矩形,可以用单调栈来处理,小于栈顶元素就不断出栈,保证栈是递增的。
定义左界和右界表示以当前元素为最高高度的连续矩形区域的左边界和右边界
在出栈时,会更新被出栈元素的右界,同时一个元素的左界在入栈前就已经确定。

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

*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值