您的位置:首页 > 其它

hdu 1506(nyoj 258)Largest Rectangle in a Histogram(最大长方形(二))(单调栈)

2017-04-03 18:45 204 查看
hdu题目链接:Largest Rectangle in a Histogram

nyoj题目链接:最大长方形(二)

思路一:

用三个数组记录,height[]记录高度,left[]记录当前高度延伸的最大左区间端点,right[]记录当前高度延伸的最大右区间端点。

然后通过left[]和right[]来缩短查询时间,对每一个高度形成的最大矩形面积进行比较

代码:

#include<stdio.h>

#define max(a,b) (a>b?a:b)
#define maxn 100000+5
typedef long long LL;
LL right[maxn],left[maxn],height[maxn];

int main()
{
LL n,cnt;
while(~scanf("%lld",&n),n)
{
for(LL i=1; i<=n; ++i)
right[i]=left[i]=i;
for(LL i=1; i<=n; ++i)
scanf("%lld",height+i);
height[0]=-1,height[n+1]=-1;
for(LL i=1; i<=n; ++i)//注意要顺序
{
cnt=i-1;
while(height[i]<=height[cnt])
{
left[i]=left[left[cnt]];//缩短查询时间
cnt=left[i]-1;
}
}
for(LL i=n; i>=1; --i)//注意要逆序
{
cnt=i+1;
while(height[i]<=height[cnt])
{
right[i]=right[right[cnt]];//缩短查询时间
cnt=right[i]+1;
}
}
LL ans=0;
for(LL i=1; i<=n; ++i)
ans=max(ans,(right[i]-left[i]+1)*height[i]);
printf("%lld\n",ans);
}
return 0;
}


思路二:单调栈,看了一下午才勉强搞懂(参考博客

它就是以某一个值为最小(最大)值,然后
dfd5
向这个值的两侧延伸,遇到大于它(小于它)的值,就将它延伸的范围扩大,当然,一般来说,要这样做的算法复杂度为o(n^2),但是借助栈这个玩意,维护其单调增(减),就可以在o(n)的时间复杂度解决这个问题。

将一元素加入栈时,先判断它是否大于(小于)栈顶元素,若是大于(小于)栈顶元素,加入栈,(从这里开始只讲维护单调增栈)否则,将栈顶元素出栈,直到栈顶元素小于要加入栈的元素。

在此过程中,需要维护向前延伸和向后延伸的问题,对于每一个要出栈的元素,很明显它已经不能往后延伸了,所以它的最大区间范围只能是它的左区间端点到当前位置(此时计算一下它的最大面积);

而当要加入栈的元素之前有n个栈元素出栈,那么说明这n个出栈的元素都是大于或者等于要入栈的元素,此时,我们需要维护入栈元素可以向前延伸多少个元素(相当于记录它的前面有多少个元素比它大,也就是找到它的左区间端点),所以每个栈顶元素都要向出栈了的元素延伸…..

最后,将所有元素出栈,即可将所有情况考虑。这样,就在o(n)的时间复杂度内解决了上述问题………具体详见代码

代码:

#include<stdio.h>
#include<string.h>

#define max(a,b) (a>b?a:b)
#define maxn 100000+5
typedef long long LL;
LL q[maxn],left[maxn];//left记录的是从这个点开始,之前有几个高度大于等于此高度

int main()
{
LL n,h;
while(~scanf("%lld",&n),n)
{
for(int i=0;i<=n+1;++i)
q[i]=-1,left[i]=0;
LL top=0,ans=0;
for(LL i=1; i<=n+1; ++i)
{
if(i<=n)
scanf("%lld",&h);
else
h=0;
if(h>q[top])
q[++top]=h,left[top]=1;
else
{
LL cnt=0;
while(h<=q[top])//(前n次)每次进行此操作时,不满足单调递增的元素(在它最大区间内)的结果将计算出来
{//当循环进行到第n+1次时,单调递增栈内的每一个元素都会(在它最大的区间内)进行一次计算
ans=max(ans,(cnt+left[top])*q[top]);
cnt+=left[top--];
}
left[++top]=cnt+1;
q[top]=h;
}
}
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐