51Nod-1102 面积最大的矩形 (DP或单调栈)

题目链接: 1102 面积最大的矩形 
基准时间限制:1 秒 空间限制:131072 KB 分值: 20  难度:3级算法题
 收藏
 关注
有一个正整数的数组,化为直方图,求此直方图包含的最大矩形面积。例如 2,1,5,6,2,3,对应的直方图如下:
 
 
面积最大的矩形为5,6组成的宽度为2的矩形,面积为10。
 
Input
第1行:1个数N,表示数组的长度(0 <= N <= 50000)
第2 - N + 1行:数组元素A[i]。(1 <= A[i] <= 10^9)
Output
输出最大的矩形面积
Input示例
6
2
1
5
6
2
3
Output示例
10
参考博客链接:https://blog.csdn.net/queuelovestack/article/details/52326276

1:DP
关键是:预处理 每个高度 对应的能“扩张”最左边left的位置,和能“扩张”最右边right的位置
 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<string.h>
 4 using namespace std;
 5 int l[50005];
 6 int r[50005];
 7 long long n[50005];//这个要放main外面,放main里面会超时
 8 int main()
 9 {
10     int N;
11     long long sum=0;
12     scanf("%d",&N);
13     for(int i=1;i<=N;i++)
14     scanf("%d",&n[i]);
15     n[0]=0;//确保left[1]的值为1
16     n[N+1]=0;//确保right[N]的值为N
17     int k;
18     for(int i=1;i<=N;i++)
19     {
20         k=i-1;
21         while(n[i]<=n[k])
22         {
23             k=l[k]-1;
24         }
25         l[i]=k+1;
26     }
27     for(int i=N;i>=1;i--)
28     {
29         k=i+1;
30         while(n[i]<=n[k])
31         {
32             k=r[k]+1;
33         }
34         r[i]=k-1;
35     }
36     for(int i=1;i<=N;i++)
37     {
38         sum=max(sum,(r[i]-l[i]+1)*n[i]);
39     }
40     printf("%lld\n",sum);
41     return 0;
42 }
 
   

2:单调栈

弄一个单调栈存储,形成一个单调递增栈。

假设这些数为2,5,8,4,1(对应下标为0-4)

 

 

 

Tip:这里入栈入的并不是number的值....

如果新进入的值比已经入栈对应的值大(或者栈空了),则入栈。(例如这里一开始栈空,所以入栈2,5,8)

当遇到新进入的值小于当前栈顶对应的值时,表明此时该“高度”不可能再往右边扩张,所以已经达到该高度扩张的最大范围。则可以进行计算算出该高度的最大值,并更新。

例如当到4时,则达到该高度扩张最大范围,高度8对应的最大值是8("(i-s.top())*number[top]"),高度8最大值的最大值计算完毕8对应位置即可出栈

(因为8对应位置出栈所以,此时5为栈定)所以高度为5对应的最大值是10("(i-s.top())*number[top]"),计算完后5对应位置出栈

但是4>2所以2还没扩张到最大范围,所以不计算2对应的的最大值

 

这是更新完后的栈。

同理:现在遇到1,1<number[s.top()]即(1<4),表明栈中对应的达到最大范围,所以高度4对应的最大值为(i-s.top())*number[s.top],即(4-1)*4=12,计算完出栈

然后,2对应位置为栈定,又因为1<2所以表明高度2也达到最大值,高度2对应的最大值为(i-s.top())*number[s.top],即(4-0)*2=8,计算完对应位置出栈。

1入栈。

Tip:    number[N]=-1;是为了让最后一个元素也能计算出最大值

 

 1 #include<stdio.h>
 2 #include<stack>
 3 using namespace std;
 4 long long number[50005];
 5 int main()
 6 {
 7     stack<int>s;
 8     int N;
 9     long long sum=0;
10     int ans;
11     scanf("%d",&N);
12     for(int i=0;i<N;i++)
13     scanf("%lld",&number[i]);
14     number[N]=-1;//确保栈中元素最大值都计算完 
15     for(int i=0;i<=N;i++)
16     {
17         if(s.empty()||number[i]>=number[s.top()])
18         {
19             s.push(i);
20         }
21         else if(number[i]<number[s.top()])
22         {
23             while(!s.empty()&&number[i]<number[s.top()])//确保栈不为空 
24             {
25                 long long num=(i-s.top())*number[s.top()];//计算 number[s.top()]该高度对应的最大值 
26                 if(num>sum) sum=num;//更新最大值 
27                 ans=s.top();//保存循环到最后"栈顶"位置 
28                 s.pop();//出栈 
29             }
30             s.push(ans);// 入栈 
31             number[ans]=number[i];//更新这个位置的number值 
32         }
33     }
34     printf("%lld\n",sum);
35     return 0;
36 }

 

 

 

转载于:https://www.cnblogs.com/bendandedaima/p/9441304.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值