最大长方形(二)

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=258

解题思路:求最大长方形面积,就是求某一个高度和这个高度最大连续长度的乘积。

自己的思路是对每一个高度从下往上扫描,对每一个高度利用分治的思想求得这个高度的最大连续长度(大于等于这个高度),可惜超时了,但是这种思想还是有用的,毕竟是之前书上看到的,虽然忘了……

分治思路:对于一个区间来说,最大连续长度在取区间左半部、右半部和中部的最大连续长度。

下面是我的代码:

#include<stdio.h>
#include<algorithm>
using namespace std;
int n, len;
long long mx;
int hist[100005];
int hight[100005];
int search(int b, int e, int h) {
	if(b == e) return 1;
	int mid = b+(e-b)/2;
	int k, max, len = 0;
	int llen = search(b, mid, h);
	int rlen = search(mid+1, e, h);
	k = mid;
	while(hist[k--] >= h) len++;
	k = mid+1;
	while(hist[k++] >= h) len++;
	if(llen > rlen) max = llen;
	else max = rlen;
	return max>len?max:len;
}
int main() {
//	freopen("data.in", "r", stdin);
	int len1, len2;
	while(scanf("%d", &n) && n) {
		for(int i = 0; i < n; i++) {
			scanf("%d", &hist[i]);
			hight[i] = hist[i];
		}
		mx = -(1<<30);
		sort(hight, hight+n);
		len = unique(hight, hight+n)-hight;
		for(int i = 0; i < len; i++) {
			int ll = search(0, n, hight[i]);
			if(mx < hight[i]*ll) {
				mx = hight[i]*ll;
			}
		}
		printf("%d\n", mx);
	}
	return 0;
}
下面说一下最优代码的思路——单调队列!!!使用一个长度栈和高度栈记录这个高度的当前最长连续上升序列。 边输入边处理。实现上,长度栈存储高度栈相应位置当前的最大连续长度,每计算一次面积就会计算最大连续长度,然后更新长度。注意到,一旦遇到高度变低的情况,说明前面高度大于等于当前高度的部分全部失效——大于等于当前高度的只在当前高度面积的计算时有效,之后就不是连续的了。计算过程中会将前面大于等于这个高度的高度全部出栈,只留下小于当前高度的部分,只有这部分在后面的连续长度计算有效, 具体过程如下:

如果最新输入的高度比高度栈顶大的话,就进行压栈操作,并且把长度1压栈;否则的话,计算一次这个高度的当前最大面积,方法是不断的累加长度计算新的最大面积并进行出栈操作直到栈顶元素小于这个高度,最后将这个高度再次压栈,并且把当前将这个高度的对应当前最大连续长度也压入高度栈,保证高度栈和长度栈的一一对应关系。

最优代码如下:

#include<cstdio>
#include<iostream>
using namespace std;
int stack[100010]={-2},len[100010];
long long ans;
int main() {
	int n,top,h;
	while(scanf("%d",&n), n) {
		top=0;ans=0;
		for(int i=0;i<=n;i++) { //注意是小于等n,相当于多循环一次 
			if(i<n)scanf("%d",&h);
			else h=-1; 			//这个-1是为了最后保证最后一个高度也会被计算 
			if(h > stack[top]) {
				stack[++top]=h;
				len[top]=1;
			} else {
				int l = 0;
				while(stack[top] >= h) {
					ans=max(ans,(long long)(l+len[top])*stack[top]);
					l += len[top--];	//累加最大连续长度 
				}
				stack[++top] = h;	//当前高度压栈 
				len[top] = l + 1;	//更新该高度最大连续长度 
			}
		}
		printf("%lld\n",ans); //使用long long类型以防面积溢出int类型 
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值