XJOI 3606 最大子矩形面积/LightOJ 1083 Histogram(单调栈/笛卡尔树)
A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure shows the histogram that consists of rectangles with the heights 2, 1, 4, 5, 1, 3, 3 measured in units where the width of the rectangles is 1.
Usually, histograms are used to represent discrete distributions, e.g., the frequencies of characters in texts. Note that the order of the rectangles, i.e., their heights, is important. Calculate the area of the largest rectangle in a histogram that is aligned at the common base line, too. The figure on the right shows the largest aligned rectangle for the depicted histogram.
Input
Input starts with an integer T (≤ 20), denoting the number of test cases.
Each case contains a line with an integer N (1 ≤ N ≤ 30000) denoting the number of rectangles. The next line contains Nspace separated positive integers (≤ 30000) denoting the heights.
Output
For each case, print the case number and the largest rectangle that can be made.
Sample Input
2
7
2 1 4 5 1 3 3
5
4 4 3 2 4
Sample Output
Case 1: 8
Case 2: 10
题意:有一系列的长条状的矩形,宽度都为1,相邻的竖立在x轴上,求最大的子矩形
胡扯:
有一回对我说道,“你学过算法么?”我略略点一点头。他说,“学过算法,……我便考你一考。XJOI的最大子矩形面积,怎样写的?”我想,AKIOI的人,怎么也来考我?便回过脸去,不再理会。孔乙己等了许久,很恳切的说道,“不能写罢?……我教给你,记着!这些算法应该记着。将来AKIOI的时候,秒题要用。”我暗想我和IOI的等级还很远呢,而且IOI也从不将这种题搬去;又好笑,又不耐烦,懒懒的答他道,“谁要你教,不是用单调栈胡搞毛搞么?”孔乙己显出极高兴的样子,将两个指头的长指甲敲着键盘,点头说,“对呀对呀!……最大子矩形面积有四样写法,你知道么?”我愈不耐烦了,努着嘴走远。孔乙己刚打开了c++,想在上面写代码,见我毫不热心,便又叹一口气,显出极惋惜的样子。
题解:
这题的确有四种解法
单调栈、笛卡尔树、类似kmp的解法、一种st表
嗯,后面两种我连名字都说不准确,所以还是不讲了
主要写两种常用的解法
首先是单调栈
单调栈就是一种栈内单调的数据结构,至于怎么维护,比如说一个单调递增的单调栈,你只需要在每加入一个数的时候,把所有比当前数大的栈顶全部弹掉就可以了
如果一个数被弹掉了,说明他能控制的矩形也已经到头了,所以就可以统计答案了,答案就是高度乘以(出去时间-进入时间)
然后唯一要注意的是该数的进入时间是第一个比他小的数的进入时间+1(他在栈中时下面的元素),而不是i,如果直接减的话就用进入时间就可以了
代码如下:
#include<stack>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; struct node
{
int time,val;
};
int n,a[],b[];
stack<node> s;
long long ans; int main()
{
scanf("%d",&n);
for(int i=; i<=n; i++)
{
scanf("%d",&a[i]);
}
for(int i=; i<=n; i++)
{
int w=i;
while((!s.empty())&&s.top().val>a[i])
{
int ti=s.top().time;
w=ti;
int v=s.top().val;
ans=max(ans,1ll*(i-ti)*v);
s.pop();
}
s.push((node){w,a[i]});
}
while(!s.empty())
{
int ti=s.top().time;
int v=s.top().val;
ans=max(ans,1ll*(n-ti+)*v);
s.pop();
}
printf("%lld\n",ans);
}
然后是笛卡尔树
笛卡尔树的中序遍历就是原序列(二叉搜索树性质),而他的每个节点的值都保证是其子树中的极值(堆性质)
笛卡尔树是可以O(n)构建的
将点i先扔到i-1的儿子下,然后比较i-1的所有祖先,一直找到第一个值比a[i]小的祖先,把这颗祖先的右儿子改成他,把原来的右儿子改成他的左儿子
均摊分析复杂度是O(n)
建出了树可以直接用size*tr[i].num来算出最大子矩形面积
不过我是直接记录每个点的pos然后瞎搞的
代码如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; struct node
{
int fa,ls,rs,num,pos;
}tr[];
int a[],n;
long long ans; void dfs(int pos,int l,int r)
{
if(l>r) return ;
ans=max(ans,1ll*(r-l+)*a[pos]);
dfs(tr[pos].ls,l,tr[pos].pos-);
dfs(tr[pos].rs,tr[pos].pos+,r);
} int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
}
tr[].num=;
tr[].rs=;
tr[].num=a[];
tr[].pos=;
for(int i=;i<=n;i++)
{
tr[i].num=a[i];
tr[i].pos=i;
int p;
for(p=i-;tr[i].num<tr[p].num;p=tr[p].fa);
tr[i].ls=tr[p].rs;
tr[p].rs=i;
tr[i].fa=p;
}
dfs(tr[].rs,,n);
printf("%lld\n",ans);
}
XJOI 3606 最大子矩形面积/LightOJ 1083 Histogram(单调栈/笛卡尔树)的更多相关文章
- 2019牛客暑期多校训练营(第二场)-H Second Large Rectangle(次大子矩阵,降维,直方图+单调栈)
题目链接:https://ac.nowcoder.com/acm/contest/882/H 题目:给n×m的由01组成的矩阵,求次大全1子矩阵的大小. 思路:第一步还是降维操作,用a[i][j]记录 ...
- poj 2559 最大矩形面积(单调栈)
题目:输入一个整数n,代表有n个 1(宽度) * h[i](高度)的矩形.接下来n个数依次给定一个矩形高度的高度h[i](i<=n). 求:在给定的依次排列的这堆矩形构成的图形里用一个矩形圈出 ...
- Vijos1055 奶牛浴场(极大化思想求最大子矩形)
思路详见 王知昆<浅谈用极大化思想解决最大子矩形问题> 写得很详细(感谢~....) 因为不太会用递推,所以用了第一种方法,时间复杂度是O(n^2),n为枚举的点数,对付这题绰绰有余 思路 ...
- Histogram LightOJ - 1083
Histogram LightOJ - 1083 题意:给出一个直方图,由n个长条组成,它们的x轴上坐标分别为1-n,读入n之后读入的一行中,第i个表示x轴上坐标为i的长条长度.求直方图最大的正方形面 ...
- [LeetCode] Rectangle Area 矩形面积
Find the total area covered by two rectilinear rectangles in a2D plane. Each rectangle is defined by ...
- POJ 1151 Atlantis(线段树-扫描线,矩形面积并)
题目链接:http://poj.org/problem?id=1151 题目大意:坐标轴上给你n个矩形, 问这n个矩形覆盖的面积 题目思路:矩形面积并. 代码如下: #include<stdio ...
- 25.按要求编写一个Java应用程序: (1)编写一个矩形类Rect,包含: 两个属性:矩形的宽width;矩形的高height。 两个构造方法: 1.一个带有两个参数的构造方法,用于将width和height属性初化; 2.一个不带参数的构造方法,将矩形初始化为宽和高都为10。 两个方法: 求矩形面积的方法area() 求矩形周长的方法perimeter() (2)通过继承Rect类编写一个具有
package zhongqiuzuoye; //自己写的方法 public class Rect { public double width; public double height; Rect( ...
- 扫描线 + 线段树 : 求矩形面积的并 ---- hnu : 12884 Area Coverage
Area Coverage Time Limit: 10000ms, Special Time Limit:2500ms, Memory Limit:65536KB Total submit user ...
- 【HDU 1542】Atlantis(线段树+离散化,矩形面积并)
求矩形面积并,离散化加线段树. 扫描线法: 用平行x轴的直线扫,每次ans+=(下一个高度-当前高度)*当前覆盖的宽度. #include<algorithm> #include<c ...
随机推荐
- update project maven项目的时候出错
preference node "org.eclipse.wst.validation"has been remove 上面的错误是因为修改包名无法互相引入导致的,仅仅需要将Ecl ...
- exited with code 1
brcc32 command line for "Project1.vrc" c:\program files\embarcadero\rad studio\9.0\bin\c ...
- [ 原创 ] Linux下查找指定类型文件以及删除
find ./ -name "*.lok" // 查找文件find ./ -name "*.lok" |xargs rm -fr // 查找文件并删除
- nginx-rtmp-module--------------WIKI
https://github.com/arut/nginx-rtmp-module/wiki/Directives#idle_streams ============================= ...
- centos7 安装 rabbitmq
主题 因为自己学习项目可能会用到rabbitmq..我又是第一次学习.以前没安装过.所以简单记录下我在centos7环境下安装rabbitmq的过程步骤,下次可以参考. 步骤 1.杂七杂八的东西 安装 ...
- <转>杜绝 Defunct进程 僵尸进程
http://hanover.iteye.com/blog/881972 在测试基于 DirectFB+Gstreamer 的视频联播系统的一个 Demo 的时候,其中大量使用 system 调用的语 ...
- url_encode and url_decode in Shell
之前写过一版 shell下解码url,下面给出另外一个版本 from https://gist.github.com/cdown/1163649 function urlencode() { loca ...
- percona xtradb cluster test
docker run --rm -ti -e CLUSTER_NAME=test -e MYSQL_ALLOW_EMPTY_PASSWORD=1 --entrypoint="bash&quo ...
- python grpc
pip install grpcio pip install grpcio-tools python -m grpc_tools.protoc -I. --python_out=. --grpc_py ...
- 201671010140. 2016-2017-2 《Java程序设计》java学习第十六周
java学习第十六周-并发 本周,学习了Java中线程,并发的知识,在老师的带领下,进行了对知识的理解学习,以及对实验的运行讲解,对这一块内容掌握的还可以,在自主编程中,也能够完成.线, ...