poj 2796

来源:互联网 发布:淘宝上怎么设置折扣 编辑:程序博客网 时间:2024/06/05 09:43

poj 2796


原题

题意:

给定一个长度为n(n<105)的非负整数序列a,定义函数f(l,r)=(minri=la[i])(ri=la[i]),求f(l,r)的最大值及其对应的lr

思路:

对于ri=l(a[i])可以通过前缀和相减O(1)得到。
当最小值a[i]确定时,由于序列a是非负整数序列,区间越大sum值越大,故我们希望在保证a[i]是区间最小值的同时使得区间长度rl+1尽可能大,这里可以用单调栈处理。
枚举每个点为区间最小值,取所有情况的最大值,复杂度O(n)
注意答案会爆int。

单调栈:

# include<stdio.h>const int NMax=100000;int n, ansL, ansR, in[NMax+1], range[NMax+1][2];long long sum[NMax+1], ans;struct Stack{    int id[NMax+1];    int top;    void Init(){top=0;}    void Pop(){top--;}    void Push(int i){id[top++]=i;}    bool Empty(){return top==0;}    int Head(){return id[top-1];}}sta;int main(){    int i;    scanf("%d", &n);    ans=(1<<31);    sum[0]=0;    sta.Init();    for(int i=1; i<=n; i++){        scanf("%d", in+i);        sum[i]=sum[i-1]+in[i];    }    for(int i=1; i<=n; i++){        while(!sta.Empty() && in[sta.Head()]>=in[i]){            range[sta.Head()][1]=i-1;            sta.Pop();        }        range[i][0]=sta.Empty()?1:sta.Head()+1;        sta.Push(i);    }    while(!sta.Empty()){        range[sta.Head()][1]=n;        sta.Pop();    }    for(int i=1; i<=n; i++){        long long tans;        tans=(sum[range[i][1]]-sum[range[i][0]-1])*in[i];        if(tans>ans){           ans=tans;           ansL=range[i][0];           ansR=range[i][1];        }    }    printf("%lld\n%d %d\n", ans, ansL, ansR);    return 0;}
0 0