poj 2559 & hdu 1506 Largest Rectangle in a Histogram 笛卡尔树

题目:

http://poj.org/problem?id=2559

题意:

有n个高度不等的矩形,问这些矩形的所能组成的新矩形的最大面积

思路:

单调栈,dp都可以做,笛卡尔树也可以做。按出现的次序做val,矩形高度做pri,然后O(n)建小顶堆的笛卡尔树,可以惊奇的发现,对于树上的每个节点,以它作为高的新矩形的面积就是以它为根的子树大小乘以它的高,为什么会这样?仔细想想构建小顶堆的笛卡尔树过程,就明白了

#include 
#include 
#include 
#include 

using namespace std;

typedef long long ll;
const int N = 100000 + 10, INF = 0x3f3f3f3f;
struct node
{
    int val, pri, fat, son[2];
    friend bool operator< (node a, node b)
    {
        return a.val < b.val;
    }
    void init(int _val, int _pri, int _fat)
    {
        val = _val, pri = _pri, fat = _fat;
        son[0] = son[1] = 0;
    }
}tr[N];
int root;
int top, stk[N];
ll ans;
//int cartesian_build(int n)
//{
//    top = 0;
//    for(int i = 1; i <= n; i++)
//    {
//        int k = top;
//        while(k > 0 && tr[stk[k-1]].pri > tr[i].pri) k--;
//        if(k != 0)
//        {
//            tr[i].fat = stk[k-1];
//            tr[stk[k-1]].son[1] = i;
//        }
//        if(k != top)
//        {
//            tr[stk[k]].fat = i;
//            tr[i].son[0] = stk[k];
//        }
//        stk[k++] = i;
//        top = k;
//    }
//    return stk[0];
//}
//另外一种O(n)构建笛卡尔树的方式,特点是代码很短
int cartesian_build(int n)
{
    for(int i = 1; i <= n; i++)
    {
        int k = i - 1;
        while(tr[k].pri > tr[i].pri) k = tr[k].fat;
        tr[i].son[0] = tr[k].son[1];
        tr[k].son[1] = i;
        tr[i].fat = k;
        tr[tr[i].son[0]].fat = i;//很多人没加这句,父节点关系就会乱掉,但到目前为止交到OJ上不会发生错误,因为此时这个点已不在最右链上,不会用到其父节点了
    }
    return tr[0].son[1];
}
int dfs(int x)
{
    if(! x) return 0;
    int sz = dfs(tr[x].son[0]);
    sz += dfs(tr[x].son[1]);
    ans = max(ans, (ll)(sz + 1) * tr[x].pri);
    return sz + 1;
}
int main()
{
    int n, a;
    while(scanf("%d", &n), n)
    {
        tr[0].init(0, 0, 0);
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &a);
            tr[i].init(i, a, 0);
        }
        root = cartesian_build(n);
        ans = 0;
        dfs(root);
        printf("%lld\n", ans);
    }
    return 0;
}

你可能感兴趣的:(笛卡尔树)