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的更多相关文章

  1. XJOI 3606 最大子矩形面积/LightOJ 1083 Histogram(单调栈/笛卡尔树)

    A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rec ...

  2. 1083 - Histogram

    1083 - Histogram   PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 64 MB A hist ...

  3. lightoj刷题日记

    提高自己的实力, 也为了证明, 开始板刷lightoj,每天题量>=1: 题目的类型会在这边说明,具体见分页博客: SUM=54; 1000 Greetings from LightOJ [简单 ...

  4. [LeetCode] Largest Rectangle in Histogram 直方图中最大的矩形

    Given n non-negative integers representing the histogram's bar height where the width of each bar is ...

  5. poj 2559 Largest Rectangle in a Histogram - 单调栈

    Largest Rectangle in a Histogram Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19782 ...

  6. 区间DP LightOJ 1422 Halloween Costumes

    http://lightoj.com/volume_showproblem.php?problem=1422 做的第一道区间DP的题目,试水. 参考解题报告: http://www.cnblogs.c ...

  7. LeetCode 笔记系列 17 Largest Rectangle in Histogram

    题目: Largest Rectangle in Histogram Given n non-negative integers representing the histogram's bar he ...

  8. LeetCode: Largest Rectangle in Histogram(直方图最大面积)

    http://blog.csdn.net/abcbc/article/details/8943485 具体的题目描述为: Given n non-negative integers represent ...

  9. LightOj 1298 - One Theorem, One Year(DP + 欧拉)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1298 题意:给你两个数 n, p,表示一个数是由前 k 个素数组成的,共有 n 个素数 ...

随机推荐

  1. 浅谈JavaScript的事件(事件委托)

    事件处理程序为Web程序提供了系统交互,但是如果页面中的事件处理程序太多,则会影响页面的性能.每个函数都是对象,都会占用内存,内存中对象越多,性能越差.需要事先为DOM对象指定事件处理程序,导致访问D ...

  2. c# 扩展方法奇思妙用基础篇五:Dictionary<TKey, TValue> 扩展

    Dictionary<TKey, TValue>类是常用的一个基础类,但用起来有时确不是很方便.本文逐一讨论,并使用扩展方法解决. 向字典中添加键和值 添加键和值使用 Add 方法,但很多 ...

  3. 【POJ 1159】Palindrome

    [POJ 1159]Palindrome 近期各种题各种奇葩思路已经司空见惯了...又新出个滚动数组= = 该题另一点须要知道 最少须要补充的字母数 = 原序列S的长度 - S和S'的最长公共子串长度 ...

  4. STM32的低功耗设置

    因为产品需求,系统功耗是一个很重要的考虑方面.好好看下STM32F103的低功耗问题,以便编写驱动. 1.STM32的电源 1.1 STM32电源框图 上面的电源中需要注意的是后备供电区域,这个部分由 ...

  5. android 提示

    1.Toast: Toast toast=new Toast(context); Toast.makeText(context, text, duration);//返回值为Toast toast.s ...

  6. YTU 2455: Pefect 数字

    2455: Pefect 数字 时间限制: 1 Sec  内存限制: 128 MB 提交: 749  解决: 146 题目描述 小明和小林做数字游戏,他们的游戏规则如下: 小明说出一个数字n,小林说出 ...

  7. asp+jQuery解决中文乱码

    1. [代码][ASP/Basic]代码 '在客户端使用javascript的escape()方法对数据进行编码,在服务器端使用对等的VbsUnEscape()对数据进行解码,同样在服务器端使用Vbs ...

  8. kafka条件查询excel拼接

    1 SELECT COUNT(*) FROM wiseweb_crawler_metasearch_page20171214 WHERE (content like '%内蒙古%'or content ...

  9. hihocoder-1347 小h的树上的朋友(lca+线段树)

    题目链接: 小h的树上的朋友 时间限制:18000ms 单点时限:2000ms 内存限制:512MB 描述 小h拥有n位朋友.每位朋友拥有一个数值Vi代表他与小h的亲密度.亲密度有可能发生变化. 岁月 ...

  10. 百度地图API应用之获取用户的具体位置

    功能的大概:用户通过点击地图上面的位置,在地图上面进行描点,然后再把获取的到的地理位置保存到地图上面的地址栏目中. 主要是百度地图API的使用 .代码如下: var map = new BMap.Ma ...