HDU 1506 Largest Rectangle in a Histogram(单调栈、笛卡尔树)
题意:给定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(单调栈、笛卡尔树)的更多相关文章
- HDU - 1506 Largest Rectangle in a Histogram (单调栈/笛卡尔树)
题意:求一个直方图中最大矩形的面积. 很经典的一道问题了吧,可以用单调栈分别求出每个柱子左右两边第一个比它低的柱子(也就相当于求出了和它相连的最后一个比它高的柱子),确定每个柱子的左右边界,每个柱子的 ...
- hdu 1506 Largest Rectangle in a Histogram(单调栈)
L ...
- HDU 1506 Largest Rectangle in a Histogram (dp左右处理边界的矩形问题)
E - Largest Rectangle in a Histogram Time Limit:1000MS Memory Limit:32768KB 64bit IO Format: ...
- HDU 1506 Largest Rectangle in a Histogram set+二分
Largest Rectangle in a Histogram Problem Description: A histogram is a polygon composed of a sequenc ...
- 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 ...
- HDU 1506 Largest Rectangle in a Histogram(区间DP)
题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1506 题目: Largest Rectangle in a Histogram Time Limit: ...
- 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 ...
- 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 ...
- hdu 1506 Largest Rectangle in a Histogram——笛卡尔树
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1506 关于笛卡尔树的构建:https://www.cnblogs.com/reverymoon/p/952 ...
随机推荐
- Table中采用JQuery slideToggle效果的问题
需求:用JQuery实现,点击最上边的粗加号时,对所有含有子表的Tr进行展开,点击 + 号时,只对当前Tr的下一个tr内容的动态隐藏和显示: 问题:JQuery的slideToggle() slide ...
- sass相关随笔
安装 下载ruby并且安装 点击这里 打开命令行输入 gem install sass 我使用的是sublime text3 还需要下载三个插件 sass -- 可以帮助你语法高亮 sass buil ...
- aar、jar、so的引入和aar打包包含so、aar、jar文件
so依赖 1,先建本地仓库,指向so放置的目录
- uLua学习之数据交互(三)
前言 在上节中,大概谈了一下如何在lua脚本中调用unity3d中的方法来创建游戏物体,这只是很小的一个方面,uLua的优势在于对unity3d中C#语言的扩展和定制.那么如何扩展和定制呢?其中的数据 ...
- [Jira]启动报错无法删除缓存文件felix-cache的解决方法
背景: 由于公司机房停电,jira服务器在停电期间需要关机处理,然而待重启启动服务时,jira出现报错,页面报错信息如下: Unable to clean the cache directory: / ...
- 如何查看与显示oracle表的分区信息
显示分区表信息 显示数据库所有分区表的信息:DBA_PART_TABLES 显示当前用户可访问的所有分区表信息:ALL_PART_TABLES 显示当前用户所有分区表的信息:USER_PART_TAB ...
- es6 随笔
记录一些学习es6中学习的新特性,挺有用,作为日后复习es6用,便于记忆. 1.变量定义let和const es6用let.const代替,let是定义块级作用域中的变量,const声明之后必须赋值, ...
- AppScale3.01
平台: Ubuntu 类型: 虚拟机镜像 软件包: appscale appscale-tools app appscale appserver basic software cloud comput ...
- IOS 自定义导航栏背景
//- (void)setBackgroundImage:(UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics NS_AV ...
- Spark的基本概念及工作原理
Spark作业的基本概念 -Application:用户自定义的Spark程序,用户提交后,Spark为App分配资源将程序转换并执行. -Driver Program:运行Application的m ...