题目描述
分析
题目意思就是找子区间的和乘区间最小值的最小值;
1.纯暴力。。。肯定TLE.
2.枚举最小值,找两边第一个比它小的,求区间和。
(肯定第二种)。。。
实现
纯循环的话肯定不行,这时候需要一点小优化——单调栈;
既然枚举最小值的话,复杂度只要 O(n),可以用前缀和求区间和,接下来就是如何用单调栈实现了
如果这个数小于栈顶元素,且这个数一定在栈顶元素后出现,那么以栈顶元素为最小值的区间一定在这个数左边一个数,用一个数组记录一下下标,这就是栈顶元素区间的右边界,然后pop掉,当栈顶元素小于这个数时,那么以这个数为最小值的区间左边界即为栈顶元素右,这同时也保证了求栈顶元素答案时左边界的提前处理。
下面放代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 1e7;
int n,m,a[maxn],l[maxn],ans,sum[maxn];
stack<int>q;
signed main() {
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i];
a[n+1]=0,sum[n+1]=sum[n];
ans=0;
for(int i=1;i<=n+1;i++){
while(!q.empty()&&a[i]<a[q.top()]){
ans=max(ans,(sum[i-1]-sum[l[q.top()]])*a[q.top()]);
q.pop();
}
if(!q.empty()) l[i]=q.top();//i这个数左边界处理
else l[i]=0;
q.push(i);
}
printf("%lld",ans);
return 0;
}
标签:int,题解,元素,栈顶,最小值,良好,maxn,感觉,区间
From: https://www.cnblogs.com/dfxjlsx/p/18024414