CF gym: Feel Good(单调栈)

CF gym: Feel Good(单调栈)_第1张图片

题意:给n个数字(0 <= n <= 100000),定义某区间的高兴值为该区间的元素总和乘以区间内的最小元素值。求出最大的高兴值。

思路:用单调栈求出每个元素左边和右边最近的比自己小的元素的位置,再遍历一遍找出最大值即可。

# include 
# 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;
    stackst;
    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);
}


转载于:https://www.cnblogs.com/junior19/p/6729884.html

你可能感兴趣的:(CF gym: Feel Good(单调栈))