Histogram LightOJ - 1083
题意:给出一个直方图,由n个长条组成,它们的x轴上坐标分别为1-n,读入n之后读入的一行中,第i个表示x轴上坐标为i的长条长度。求直方图最大的正方形面积。
方法:
核心是求出每个长条向左右可以"扩展"的最大长度。
法一:单调栈
将n个元素的编号依次入栈。每次入栈前,设要入栈的编号为x,对应长度为l,将栈顶的编号对应的长度大于等于l的所有编号出栈(由于此题的一些特性,将“大于等于”改为“大于”也可以使用,但这不是标准的单调栈)。这之后,栈顶元素就是x能扩展到的最左端的端点减1(注意,是减1)。对于某个元素,其出栈的那一刻,使其出栈的x减一就是其能扩展到的最右侧的端点。
#include<cstdio>
#include<algorithm>
using namespace std;
int T,n,ans,len;
int st[],a[],l[],r[];
void push(int idx)
{
while(len>&&a[st[len]]>=a[idx]) r[st[len--]]=idx-;
l[idx]=st[len];
st[++len]=idx;
}
int main()
{
int i,TT;
scanf("%d",&T);
for(TT=;TT<=T;TT++)
{
scanf("%d",&n);
for(i=;i<=n;i++)
scanf("%d",&a[i]);
len=;
ans=;
for(i=;i<=n;i++)
push(i);
while(len>) r[st[len--]]=n;
for(i=;i<=n;i++)
ans=max(ans,a[i]*(r[i]-l[i]));
printf("Case %d: %d\n",TT,ans);
}
return ;
}
(由于题目的某些特性,即使单调栈在push时不把相同的pop出来也可以过。然而正确的单调栈一般都要把相同的也pop出来)
#include<cstdio>
#include<algorithm>
using namespace std;
int T,n,ans,len;
int st[],a[],l[],r[];
void push(int idx)
{
while(len>&&a[st[len]]>a[idx]) r[st[len--]]=idx-;
l[idx]=st[len];
st[++len]=idx;
}
int main()
{
int i,TT;
scanf("%d",&T);
for(TT=;TT<=T;TT++)
{
scanf("%d",&n);
for(i=;i<=n;i++)
scanf("%d",&a[i]);
len=;
ans=;
for(i=;i<=n;i++)
push(i);
while(len>) r[st[len--]]=n;
for(i=;i<=n;i++)
ans=max(ans,a[i]*(r[i]-l[i]));
printf("Case %d: %d\n",TT,ans);
}
return ;
}
法二:奇奇怪怪的方法,类似链表/kmp的预处理
left[i]和right[i]分别表示能扩展到的最左/右侧的高度小于等于它的长条的编号。看起来可能很慢,但是实际上均摊复杂度O(n)。
#include<cstdio>
#include<algorithm>
using namespace std;
int T,n,ans;
int a[],left[],right[];
int main()
{
int TT,i;
scanf("%d",&T);
for(TT=;TT<=T;TT++)
{
ans=;
scanf("%d",&n);
for(i=;i<=n;i++)
scanf("%d",&a[i]);
for(i=;i<=n;i++)
{
left[i]=i;
while(left[i]>&&a[left[i]-]>=a[i]) left[i]=left[left[i]-];
}
for(i=n;i>=;i--)
{
right[i]=i;
while(right[i]<n&&a[right[i]+]>=a[i]) right[i]=right[right[i]+];
}
for(i=;i<=n;i++)
ans=max(ans,a[i]*(right[i]-left[i]+));
printf("Case %d: %d\n",TT,ans);
}
}
法三:一个区间由区间最小值控制。对于某一个区间,答案要么包含这个最小值,要么在最小值左侧区间取,要么在右侧区间取。因此预处理解决RMQ,然后分治解决。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int T,TT,n;
int minn[][],a[];
int query(int l,int r)
{
int k=;
while((<<(k+))<=r-l+) ++k;
return a[minn[k][l]]>a[minn[k][r-(<<k)+]]?minn[k][r-(<<k)+]:minn[k][l];
}
int get(int l,int r)
{
if(l>r) return ;
if(l==r)
return a[l];
int pos=query(l,r);
return max(max(get(l,pos-),get(pos+,r)),a[pos]*(r-l+));
}
int main()
{
int i,j;
scanf("%d",&T);
for(TT=;TT<=T;TT++)
{
memset(minn,,sizeof(minn));
memset(a,,sizeof(a));
scanf("%d",&n);
for(i=;i<=n;i++)
scanf("%d",&a[i]);
for(i=;i<=n;i++)
minn[][i]=i;
for(i=;(<<i)<=n;i++)
for(j=;j<=n-(<<i)+;j++)
minn[i][j]=a[minn[i-][j]]>a[minn[i-][j+(<<(i-))]]?minn[i-][j+(<<(i-))]:minn[i-][j];
printf("Case %d: %d\n",TT,get(,n));
}
return ;
}
Histogram LightOJ - 1083的更多相关文章
- XJOI 3606 最大子矩形面积/LightOJ 1083 Histogram(单调栈/笛卡尔树)
A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rec ...
- 1083 - Histogram
1083 - Histogram PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 64 MB A hist ...
- lightoj刷题日记
提高自己的实力, 也为了证明, 开始板刷lightoj,每天题量>=1: 题目的类型会在这边说明,具体见分页博客: SUM=54; 1000 Greetings from LightOJ [简单 ...
- [LeetCode] Largest Rectangle in Histogram 直方图中最大的矩形
Given n non-negative integers representing the histogram's bar height where the width of each bar is ...
- poj 2559 Largest Rectangle in a Histogram - 单调栈
Largest Rectangle in a Histogram Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 19782 ...
- 区间DP LightOJ 1422 Halloween Costumes
http://lightoj.com/volume_showproblem.php?problem=1422 做的第一道区间DP的题目,试水. 参考解题报告: http://www.cnblogs.c ...
- LeetCode 笔记系列 17 Largest Rectangle in Histogram
题目: Largest Rectangle in Histogram Given n non-negative integers representing the histogram's bar he ...
- LeetCode: Largest Rectangle in Histogram(直方图最大面积)
http://blog.csdn.net/abcbc/article/details/8943485 具体的题目描述为: Given n non-negative integers represent ...
- LightOj 1298 - One Theorem, One Year(DP + 欧拉)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1298 题意:给你两个数 n, p,表示一个数是由前 k 个素数组成的,共有 n 个素数 ...
随机推荐
- attribute constructor&destructor
attribute constructor&destructor 在看openwrt里libnl-tiny这个库的时候,遇到了C里面的构造函数这个概念. static void __init ...
- Vue生命周期方法。
- 项目问题总结2:GUID区分大写和小写吗?
问题描写叙述: 近期在做项目的过程中,遇到一个问题,将从基础系统查询出来的课程ID作为參数去考评系统里查询考试信息,却什么也查不出来,调试了半天不知道什么原因. 问题分析: 静下心来思考一下,能够肯定 ...
- 三种方法打印 main函数的返回地址的值(old EIP)(用途,你懂得!)
这里能够简单的改动随意函数的返回地址.能够做到自己定义EIP的指向,就可以运行当前进程空间的随意指令,这里仅仅是让大家更清楚栈帧结构,没有涉及跨进程的inline HOOK 等,后面会陆续讲下读取随意 ...
- Android 的assets文件资源与raw文件资源读取
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/zpf8861/article/details/34504183 res/raw和assets的同 ...
- (C)strcpy ,strncpy与strlcpy
1. 背景 好多人已经知道利用strncpy替代strcpy来防止缓冲区越界. 但是如果还要考虑运行效率的话,也许strlcpy是一个更好的方式. 2. strcpy strcpy 是依据 /0 作为 ...
- html5--6-40 CSS边框
html5--6-40 CSS边框 实例 div动态阴影 学习要点 掌握CSS边框属性的使用 元素的边框就是围绕元素内容和内边距的一条或多条线. 元素的边框属性: border 简写属性,用于把针对四 ...
- STL Algorithms 之 unique
C++的文档中说,STL中的unique是类似于这样实现的: template <class ForwardIterator> ForwardIterator unique ( Forwa ...
- RandomUtils
package com.cc.hkjc.util; import java.util.Random; public class RandomUtils { /** * 获取count个随 ...
- C#参数数组的用法1
C# 参数数组 有时,当声明一个方法时,您不能确定要传递给函数作为参数的参数数目.C# 参数数组解决了这个问题,参数数组通常用于传递未知数量的参数给函数. params 关键字 在使用数组作为形参时, ...