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 ...
随机推荐
- PHP笔试题和面试题
1.不用新变量直接交换现有两个变量的值 (1)list($a,$b)=array($b,$a); (2)a=a+b,b=a-b,a=a-b 2.PHP数字金额转大小格式,同时说明思路 function ...
- 有趣的 验证JS只能输入正整数
<html> <head> <title>只能输入正整数</title> </head> <body> 兑换数量:<inp ...
- IE浏览器与非IE浏览器JS日期兼容性问题处理
执行语句 console.log(new Date("2017-07-04 18:40").getTime()); 在IE浏览器中打印出:NAN 在非IE浏览器中打印出:14991 ...
- asp.net后台调用前台js代码
为了通过ajax异步获取数据,我通过使用jquery的$(function{})方法,在页面加载时发送ajax请求,获取相关的数据.但是遇到了一个问题,当我发送的ajax请求需要根据传过来的URL参数 ...
- C#对INI文件读写
C#本身没有对INI格式文件的操作类,可以自定义一个IniFile类进行INI文件读写. using System; using System.Collections.Generic; using S ...
- 使用Kubernetes的java-client实现Deployment的部署及更新操作
1. 背景介绍 需求: 针对多种协议SDK构造探针,测试公司接入机服务状况(每一个探针应对单一接入机,接入机数量可能会动态变化). 难点: 大多数协议SDK均不支持多实例运行,且部分SDK通过生成文件 ...
- 【收藏】这么多WEB组件(CSS),攒一个网站够了吧?
简言 总是喜欢简单又精致的东西,美的不繁复也不张扬.这是闷骚程序员的癖好么?闲来无事,把收集到的部分WEB组件整理汇总一下,攒一个逼格高一点的网站够了吧? 1 表单(form)相关 1.1 输入框(i ...
- Sometimes it takes going through something so awful to realize the beauty that is out there in this world.
Sometimes it takes going through something so awful to realize the beauty that is out there in this ...
- MySQL-数据类型及选择
一.数据类型 详见:http://www.runoob.com/mysql/mysql-data-types.html 二.类型选择 整形>date,time>enum,char>v ...
- Hadoop 分片、分组与排序
首先需要明确的是,hadoop里的key一定要是可排序的,要么key自身实现了WritableComparator接口,要么有一个排序类可以对key进行排序.如果key本身不实现WritableCom ...