题意:给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); }