题意:给n个数字(0 <= n <= 100000),定义某区间的高兴值为该区间的元素总和乘以区间内的最小元素值。求出最大的高兴值。
思路:用单调栈求出每个元素左边和右边最近的比自己小的元素的位置,再遍历一遍找出最大值即可。
# include <bits/stdc++.h>
# define ll long long
# define INF 0x3f3f3f3f
# define maxn 100000
using namespace std;
int l[maxn+13]={0}, r[maxn+13]={0}, a[maxn+13], n, al, ar;
ll sum[maxn+13], imax=-INF;
int main()
{
//freopen("feelgood.in","r",stdin);
//freopen("feelgood.out","w",stdout);
scanf("%d",&n);
a[0] = a[n+1] = -INF;
stack<int>st;
r[n+1] = n+1;
for(int i=1; i<=n; ++i)
{
scanf("%d",&a[i]);
sum[i] = sum[i-1] + (ll)a[i];
}
st.push(0);
for(int i=1; i<=n; ++i)//左边
{
while(a[i]<=a[st.top()]) st.pop();
l[i] = st.top();
st.push(i);
}
while(!st.empty()) st.pop();
st.push(n+1);
for(int i=n; i>=1; --i)//右边
{
while(a[i]<=a[st.top()]) st.pop();
r[i] = st.top();
st.push(i);
}
for(int i=1; i<=n; ++i)
{
ll t = (ll)a[i]*(sum[r[i]-1] - sum[l[i]]);
if(t > imax)
{
imax = t;
al = l[i]+1;
ar = r[i]-1;
}
}
printf("%I64d\n%d %d\n",imax, al, ar);
}