单调栈求每个数在哪些区间是最值的经典操作。
把数一个一个丢进单调栈,弹出的时候[st[top-1]+1,i-1]这段区间就是弹出的数为最值的区间。
poj2796 弹出的时候更新答案即可
#include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<cmath> #include<map> #define ll long long using namespace std; const int maxn=500010,inf=1e9; int n,top,ansl,ansr; ll ans=-1; int st[maxn],a[maxn]; ll sum[maxn]; void read(int &k) { int f=1;k=0;char c=getchar(); while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar(); k*=f; } int main() { read(n); for(int i=1;i<=n;i++)read(a[i]),sum[i]=sum[i-1]+a[i];a[++n]=-1; for(int i=1;i<=n;i++) { for(;top&&a[i]<=a[st[top]];top--) { ll val=1ll*a[st[top]]*(sum[i-1]-sum[st[top-1]]); if(val>ans)ans=val,ansl=st[top-1]+1,ansr=i-1; } st[++top]=i; } printf("%lld\n%d %d",ans,ansl,ansr); return 0; }