题意:给定n个连续排列的矩形的高,矩形的宽都为1。问最大矩形覆盖。

例如:n = 7,h[i] = (2 1 4 5 1 3 3),最大覆盖为8。

Sample Input
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0 Sample Output
8
4000

题解:

首先可以确定,最大矩形的高一定等于某个矩形的高,宽一定等于某个矩形可以向两边最大可以延伸到的范围。

维护一个非降序的单调栈,然后依次枚举矩形的高 h[i]。

当 h[i] > top()时,说明 h[i] 向左最多可以延伸到 top() + 1,然后将 i 入栈。

当 h[i] < top()时,说明 top 向右最多可以延伸到 i - 1,为了满足栈的单调,栈顶元素要不断出栈,然后按 h[i] > top()的情况处理。

最后扫一遍,找最大的 (r[i] - l[i] + 1) * h[i],就是答案。

h[i] == top() 呢?不用管。

可以看出,对于有两个以上的矩形等价(这里的等价指的是,矩形高度相同,他们的最大延伸范围也相同)时,上面处理得到的 l[i] 和 r[i] 只有其中一个的答案会是他们最大的延伸范围,所以并不影响答案。所以维护的单调栈可以是单调不降的,也可以是单调递增的。

例如:4 4 4 4,上面求出的延伸范围是(1, 4) (2, 4) (3, 4) (4, 4)。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;
typedef long long LL;
const int maxn = ;
const LL INF = 1e16; int a[maxn];
LL l[maxn], r[maxn]; int main()
{
int n;
while(~scanf("%d", &n) && n)
{
for (int i = ; i <= n; i++) scanf("%d", &a[i]); stack<int> st;
st.push(), a[n+] = ;
for (int i = ; i <= n+; i++)
{
     //若是这里改成 >= 来维护单调递增的栈的话,判断应该加一个 && (a[st.top() | a[i]),防止栈空。
while(a[st.top()] > a[i])
r[st.top()] = i-, st.pop();
l[i] = st.top()+;
st.push(i);
} LL ans = -INF;
for (int i = ; i <= n; i++)
ans = max(ans, 1ll * (r[i]-l[i]+) * a[i]); printf("%lld\n", ans);
}
}

另一种做法就是笛卡尔树了。

笛卡尔树满足的条件:

1、左子树的下标 < 根节点 < 右子树

2、根节点的值是子树中所有点的最值。

可以看出,对一颗笛卡尔树中序遍历即可得到原序列。

故此题可以构造一个笛卡尔树,答案就是所有子树中 MAX(子树结点 × 根节点的值)。

笛卡尔树可以借助单调栈构建:

按照序列的顺序,每加入一个 a[i] 时,

若栈顶元素 > a[i],则不断弹出栈顶,使栈满足单调。将最后一个被弹出的做为 i 的左儿子。(因为这一段被弹出的下标都小于 i ,并且值都大于 a[i])

然后将 i 入栈,做为原本栈顶的儿子。

时间复杂度O(n)。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;
typedef long long LL;
const int maxn = ;
const LL INF = 1e16; int a[maxn], lson[maxn], rson[maxn], fa[maxn];
LL dp[maxn];
LL ans, tmp; LL DP(int id)
{
if (id == ) return ;
if (dp[id]) return dp[id];
dp[id] = DP(lson[id]) + DP(rson[id]) + ;
ans = max(ans, 1ll * dp[id] * a[id]);
return dp[id];
} int main()
{
int n;
while(~scanf("%d", &n) && n)
{
for (int i = ; i <= n; i++) scanf("%d", &a[i]); stack<int> st;
memset(lson, , sizeof(lson));
memset(rson, , sizeof(rson));
memset(dp, , sizeof(dp));
memset(fa, , sizeof(fa)); for (int i = ; i <= n; i++)
{
if (!st.empty() && a[st.top()] > a[i])
{
while (!st.empty() && a[st.top()] > a[i])
tmp = st.top(), st.pop();
lson[i] = tmp, fa[tmp] = i;
}
if (!st.empty()) rson[st.top()] = i, fa[i] = st.top();
st.push(i);
} ans = -INF;
for (int i = ; i <= n; i++) if (!fa[i]) DP(i); printf("%lld\n", ans);
}
}

HDU 1506 Largest Rectangle in a Histogram(单调栈、笛卡尔树)的更多相关文章

  1. HDU - 1506 Largest Rectangle in a Histogram (单调栈/笛卡尔树)

    题意:求一个直方图中最大矩形的面积. 很经典的一道问题了吧,可以用单调栈分别求出每个柱子左右两边第一个比它低的柱子(也就相当于求出了和它相连的最后一个比它高的柱子),确定每个柱子的左右边界,每个柱子的 ...

  2. hdu 1506 Largest Rectangle in a Histogram(单调栈)

                                                                                                       L ...

  3. HDU 1506 Largest Rectangle in a Histogram (dp左右处理边界的矩形问题)

    E - Largest Rectangle in a Histogram Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format: ...

  4. HDU 1506 Largest Rectangle in a Histogram set+二分

    Largest Rectangle in a Histogram Problem Description: A histogram is a polygon composed of a sequenc ...

  5. hdu 1506 Largest Rectangle in a Histogram 构造

    题目链接:HDU - 1506 A histogram is a polygon composed of a sequence of rectangles aligned at a common ba ...

  6. HDU 1506 Largest Rectangle in a Histogram(区间DP)

    题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1506 题目: Largest Rectangle in a Histogram Time Limit: ...

  7. DP专题训练之HDU 1506 Largest Rectangle in a Histogram

    Description A histogram is a polygon composed of a sequence of rectangles aligned at a common base l ...

  8. Hdu 1506 Largest Rectangle in a Histogram 分类: Brush Mode 2014-10-28 19:16 93人阅读 评论(0) 收藏

    Largest Rectangle in a Histogram Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 ...

  9. hdu 1506 Largest Rectangle in a Histogram——笛卡尔树

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1506 关于笛卡尔树的构建:https://www.cnblogs.com/reverymoon/p/952 ...

随机推荐

  1. Mybatis-Plus使用全解

    前言 之前写了<SpringBoot | 第九章:Mybatis-plus的集成和使用>一文,只是简单的使用条件构造器列举了一些通用的CURD操作.本人也想写一篇通用的关于mybatis- ...

  2. ubuntu配置硬盘开机自动挂载

    1.创建/media/fly文件夹 sudo mkdir /home/fly    #根据个人喜好命名 2.获取要自动挂载的分区的UUID和分区类型TYPE sudo blkid 出现如下结果:   ...

  3. Struts2 源码分析-----Hello world

    今天第一天学习struts2,没学过怎么办,那当然是helloworld.感觉嘛,学习的基本流程都差不多,就是helloworld,开发环境,然后就是逐个按照知识点打demo,打着打着你就会发现str ...

  4. JAVA 面试重点知识个人总结

    一.集合: 1 .Collection(是java.util下的接口) 和 Collections(是java.util下的类). 2 .List, Set,是否继承自Collection接口,Map ...

  5. selenium+phantomjs报错:Unable to find a free port的分析和解决

    selenium+phantomjs报错:Unable to find a free port的分析和解决 Table of Contents 1. 现象 2. 分析 3. 解决办法 1 现象 在做项 ...

  6. jQuery学习笔记(三)

    jQuery中的事件 页面加载 原生DOM中的事件具有页面加载的内容onload事件,在jQuery中同样提供了对应的内容ready()函数. ready与onload之间的区别: onload re ...

  7. 解决移动端浏览器页面 X轴横向滚动条问题

    写web端页面的时候,总是会出现横向滚动条,即 X 轴滚动条,导致页面左右滑来滑去. 即使设置了 body,html {overflow-x:hidden;width:100%;} 也无法生效. 解决 ...

  8. 【干货】JavaScript DOM编程艺术学习笔记1-3

    从7月29号到8月8号,断断续续地看完了这本书,做了部分实践联系.总体感觉本书真的只能算是个入门,学完之后看到库的那一章才感觉是个大坑,实践中大部分应该都是用的现成的库吧,所以还要重新学习一个库,但是 ...

  9. pysnmp程序

    功能 访问远程交换机snmp数据,写入本地influxdb数据库 #!/usr/bin/env python # -*- encoding: utf-8 -*- import os, yaml, ti ...

  10. Python之HTML的解析(网页抓取一)

    http://blog.csdn.net/my2010sam/article/details/14526223 --------------------- 对html的解析是网页抓取的基础,分析抓取的 ...