第1行:1个数N,表示数组的长度(0 <= N <= 50000) 第2 - N + 1行:数组元素A[i]。(1 <= A[i] <= 10^9)
输出最大的矩形面积
6 2 1 5 6 2 3
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 }