P2422 良好的感觉
题解
1.我们没法遍历每个区间然后找出他们的最小值,所以我们考虑每个元素对答案的贡献
2.对于每一个元素来说,它的贡献等于它所在的区间长度乘上自身的值,这里的区间指的是以它为最小值的区间
3.以每个元素为最小值的区间要怎么求呢?我们将其转换成求左边第一个小和右边第一个小
对于这种问题(求序列中最近最小元素),我们建立一个栈,然后线性遍历,维护栈使其从底到顶下标有序,值也有序
如果是求左边最小值的话,我们维护栈内元素的下标成升序,值成降序。这样一来,我们可以遍历栈来找到左边第一个最小值了(有点像把升序折叠起来了?反正是个子问题)
右边同理
注意不同题细节不同,这里我们遍历找到的是第一个比i小的元素,所以它们不算在内i对答案的贡献内,空栈的含义是没有比自己小的,那就赋为端点
code
#include<bits/stdc++.h>
using namespace std;
int a[100005]={0},pre[100005]={0},l[100005]={0},r[100005]={0};
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
pre[i]=pre[i-1]+a[i];
}
stack<int> q;
for(int i=1;i<=n;i++)
{
while(q.size()&&a[q.top()]>=a[i]) q.pop();
if(q.size()) l[i]=q.top();
else l[i]=0;
q.push(i);
}
stack<int> q2;
for(int i=n;i>=1;i--)
{
while(q2.size()&&a[q2.top()]>=a[i]) q2.pop();
if(q2.size()) r[i]=q2.top();
else r[i]=n+1;
q2.push(i);
}
int ans=0;
for(int i=1;i<=n;i++) ans=max(ans,a[i]*(pre[r[i]-1]-pre[l[i]]));
cout<<ans;
return 0;
}

浙公网安备 33010602011771号