hdu1506 Largest Rectangle in a Histogram (笛卡尔树)

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1506

标解应该是DP。不过这里可以当做笛卡尔树模板题来做。笛卡尔树的构造方式为:首先我们按照横坐标从左往右进行处理,同时维护一个单调栈,保证栈里的元素高度递增。每次进来一个新的节点时,将栈里比它高的元素都弹出,并将它的左儿子设为最后一个弹出的节点,而且将先弹出的节点设为它之后弹出的那个节点的右儿子即可。为了保证结束性,可以在最右侧加入一个高度为0的点。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;
typedef long long LL;
struct node
{
    int x,y;
};
int n;
int a[110000];
stack 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;
}

你可能感兴趣的:(笛卡尔树,online,judge,hdu,bestcoder)