poj 2796 单调栈

来源:互联网 发布:开淘宝店如何做好推广 编辑:程序博客网 时间:2024/06/04 18:10

题意: 给你n个数字 定义一个区间的值为(区间内所有值的和)*(区间内的最小值) 

求所有合法区间中的最大值 并输出区间和最大值。


思路:枚举最小值,然后利用单调栈,求出每个位置的一直大于他的左端点和右端点,然后利用前缀和求值。


#include <iostream>#include <cstdio>#include <set>#include <cstring>#include <algorithm>#include <vector>#include <cmath>#include <map>#include <string>#include <cctype>using namespace std;typedef __int64 LL;const int maxn = 1e6+10;LL h[maxn];LL st[maxn];LL l[maxn];LL r[maxn];LL pre[maxn];int main(){    int n;    while(~scanf("%d",&n))    {        for(int i=1; i<=n; i++)            scanf("%I64d",&h[i]);        memset(pre,0,sizeof(pre));        LL top;        h[0]=h[n+1]=-1;        st[top=1]=0;        for(int i=1; i<=n; i++)        {            while(h[i]<=h[st[top]])                top--;            l[i]=st[top];            st[++top]=i;        }        st[top=1]=n+1;        for(int i=n; i>=1; i--)        {            while(h[i]<=h[st[top]])                top--;            r[i]=st[top];            st[++top]=i;        }        for(int i=1; i<=n; i++)        {            pre[i]+=pre[i-1]+h[i];        }        LL sum=-1;        LL ll,rr;        for(int i=1; i<=n; i++)        {            LL x=(pre[r[i]-1]-pre[l[i]])*h[i];            if(x>sum)            {                sum=x;                ll=l[i]+1;                rr=r[i]-1;            }        }        printf("%I64d\n",sum);        printf("%I64d %I64d\n",ll,rr);    }    return 0;}


0 0