单调栈求区间的最小值
前缀和求区间和
class Solution {
public:
int mintimessum(vector<int>& a) {
int n=a.size();
int ans=0;
//leftmin用于存每个元素左边第一个小于本身的数的位置
//rightmin用于存每个元素右边第一个小于本身的数的位置
vector<int>leftmin(n);
vector<int>rightmin(n);
//用单调栈维护以a[i]为最小值的区间的左右端点
stack<int>stack1;
//区间和用前缀和求
vector<int>pre(n+1);
//求前缀和,注意这里的pre[1]求的就是a[0]
for(int i=1;i<=n;i++) pre[i]=pre[i-1]+a[i-1];
//正向遍历找到每个元素作为最小值的区间的左端点
for(int i=0;i<n;i++){
while(!stack1.empty()&&a[stack1.top()]>=a[i]){
stack1.pop();
}
//注意特判一下,如果这个元素的左边没有元素了,那么就将这个区间的左端点设置为-1
leftmin[i]=stack1.empty()?-1:stack1.top();
stack1.push(i);
}
//调用无参构造函数将栈清空
stack1=stack<int>();
//逆向遍历找右边第一个小于本身的元素的位置
for(int i=n-1;i>=0;i--){
while(!stack1.empty()&&a[stack1.top()]>=a[i]){
stack1.pop();
}
//特判当这个元素的右边没有元素的时候,就标记以该元素为最小值的区间的右端点为n
rightmin[i]=stack1.empty()?n:stack1.top();
stack1.push(i);
}
//遍历所有的元素,求出以某个元素为区间的最小值*区间和的最大值
for(int i=0;i<n;i++){
//由于是前缀和pre[1]=a[0],所以要left+1,不包含区间右端点
ans=max(ans,a[i]*(pre[rightmin[i]]-pre[leftmin[i]+1]));
}
return ans;
}
};