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[]来缩短查询时间,对每一个高度形成的最大矩形面积进行比较
代码:
思路二:单调栈,看了一下午才勉强搞懂(参考博客)
它就是以某一个值为最小(最大)值,然后
dfd5
向这个值的两侧延伸,遇到大于它(小于它)的值,就将它延伸的范围扩大,当然,一般来说,要这样做的算法复杂度为o(n^2),但是借助栈这个玩意,维护其单调增(减),就可以在o(n)的时间复杂度解决这个问题。
将一元素加入栈时,先判断它是否大于(小于)栈顶元素,若是大于(小于)栈顶元素,加入栈,(从这里开始只讲维护单调增栈)否则,将栈顶元素出栈,直到栈顶元素小于要加入栈的元素。
在此过程中,需要维护向前延伸和向后延伸的问题,对于每一个要出栈的元素,很明显它已经不能往后延伸了,所以它的最大区间范围只能是它的左区间端点到当前位置(此时计算一下它的最大面积);
而当要加入栈的元素之前有n个栈元素出栈,那么说明这n个出栈的元素都是大于或者等于要入栈的元素,此时,我们需要维护入栈元素可以向前延伸多少个元素(相当于记录它的前面有多少个元素比它大,也就是找到它的左区间端点),所以每个栈顶元素都要向出栈了的元素延伸…..
最后,将所有元素出栈,即可将所有情况考虑。这样,就在o(n)的时间复杂度内解决了上述问题………具体详见代码
代码:
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; }
相关文章推荐
- hdu 1506(nyoj 258)Largest Rectangle in a Histogram(最大长方形(二))(单调栈)
- hdu 1506(nyoj 258)Largest Rectangle in a Histogram(最大长方形(二))(单调栈)
- hdu 1506(nyoj 258)Largest Rectangle in a Histogram(最大长方形(二))(单调栈)
- hdu 1506(nyoj 258)Largest Rectangle in a Histogram(最大长方形(二))(单调栈)
- hdu 1506(nyoj 258)Largest Rectangle in a Histogram(最大长方形(二))(单调栈)
- hdu 1506(nyoj 258)Largest Rectangle in a Histogram(最大长方形(二))(单调栈)
- hdu 1506(nyoj 258)Largest Rectangle in a Histogram(最大长方形(二))(单调栈)
- hdu 1506(nyoj 258)Largest Rectangle in a Histogram(最大长方形(二))(单调栈)
- hdu 1506(nyoj 258)Largest Rectangle in a Histogram(最大长方形(二))(单调栈)
- hdu 1506(nyoj 258)Largest Rectangle in a Histogram(最大长方形(二))(单调栈)
- hdu 1506(nyoj 258)Largest Rectangle in a Histogram(最大长方形(二))(单调栈)
- hdu 1506(nyoj 258)Largest Rectangle in a Histogram(最大长方形(二))(单调栈)
- hdu 1506(nyoj 258)Largest Rectangle in a Histogram(最大长方形(二))(单调栈)
- NYOJ-258/POJ-2559/HDU-1506 Largest Rectangle in a Histogram,最大长方形,dp或者单调队列!
- HDU OJ 1506 Largest Rectangle in a Histogram 和 NYOJ 258 最大长方形(二) 【单调队列】
- HDU 1506 Largest Rectangle in a Histogram(最大矩形面积、单调栈)
- Hdu 1506 Largest Rectangle in a Histogram (DP求最大长方形面积)
- hdu 1506 Largest Rectangle in a Histogram【最大长方形面积】
- hdu 1506 Largest Rectangle in a Histogram(单调栈)
- HDU 1506 Largest Rectangle in a Histogram(dp求最大子矩阵和)