hdu1506 Largest Rectangle in a Histogram (笛卡爾樹)

傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=1506

標解應該是DP。不過這裏可以當做笛卡爾樹模板題來做。笛卡爾樹的構造方式爲:首先我們按照橫座標從左往右進行處理,同時維護一個單調棧,保證棧裏的元素高度遞增。每次進來一個新的節點時,將棧裏比它高的元素都彈出,並將它的左兒子設爲最後一個彈出的節點,而且將先彈出的節點設爲它之後彈出的那個節點的右兒子即可。爲了保證結束性,可以在最右側加入一個高度爲0的點。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<bitset>

using namespace std;
typedef long long LL;
struct node
{
    int x,y;
};
int n;
int a[110000];
stack<node> s;
int ch[110000][2],fa[110000],sz[110000];
int root;
void build(int n)
{
    memset(ch,0,sizeof(ch));
    memset(fa,0,sizeof(fa));
    for (int i=1;i<=n;i++)
    {
        int last=0;
        while (!s.empty()&&s.top().y>=a[i])
        {
            if (last) ch[s.top().x][1]=last,fa[last]=s.top().x;
            last=s.top().x;
            s.pop();
        }
        if (last&&i!=n) ch[i][0]=last,fa[last]=i;
        if (i!=n) s.push({i,a[i]});
    }
    root=1;
    while(fa[root]) root=fa[root];
}

LL ans;
void dfs(int x)
{
    sz[x]=1;
    for (int i=0;i<2;i++)
        if (ch[x][i]) dfs(ch[x][i]),sz[x]+=sz[ch[x][i]];
    ans=max(ans,(LL)sz[x]*(LL)a[x]);
}
int main()
{
    while (scanf("%d",&n)==1&&n)
    {
        for (int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        a[n+1]=0;
        build(n+1);
        ans=0;
        dfs(root);
        printf("%I64d\n",ans);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章