首页 > 代码库 > UVALive 3517:Feel Good(单调栈 Grade C)

UVALive 3517:Feel Good(单调栈 Grade C)

VJ题目链接

题意:

n个数,求区间[l,r] 使得 sum[l,r]*min(a[l],a[l+1],...,a[r]) 最大。若有多种答案,输出区间最短的。若还有多组,输出最先出现的。

思路:

求出a[i]为最小数时,最大的区间范围,即求a[i]的最左边的小于a[i]的位置,最右边的位置。

坑点:

因为要最小长度区间,当最小数是0的时候,就出现了巨大的坑点……所以特判。

代码:

#include <cstdio>#include <cstring>#include <cstdlib>#define N 100010int a[N];int l[N], r[N];long long sum[N];int n;int stk[N];void getl() {    int top = 0;    for (int i = 1; i <= n; i++) {        while (top > 0 && a[stk[top-1]] >= a[i]) top--;        stk[top++] = i;        if (top == 1) l[i] = 0;        else l[i] = stk[top-2];    }}void getr() {    int top = 0;    for (int i = n; i > 0; i--) {        while (top > 0 && a[stk[top-1]] >= a[i]) top--;        stk[top++] = i;        if (top == 1) r[i] = n+1;        else r[i] = stk[top-2];    }}int main() {    int isfirst = 0;    while (scanf("%d", &n) != EOF) {        if (isfirst++) puts("");        //!isfirst++?:puts("");        sum[0] = 0;        for (int i = 1; i <= n; i++) {            scanf("%d", &a[i]);            sum[i] = a[i] + sum[i-1];        }        sum[n+1] = sum[n];        getl();        getr();                long long ans = -1;        int lans, rans;        for (int i = 1; i <= n; i++) {            long long now = (sum[r[i]-1]-sum[l[i]])*a[i];            if (ans < now) {                ans = now;                 lans = l[i]+1;                rans = r[i]-1;                //This is a Great 坑                if (ans == 0) {                    lans = i;                    rans = i;                }                //The Great 坑 End                            } else if (ans == now) {                if (rans-lans+1 > r[i]-l[i]-1) {                    lans = l[i]+1;                    rans = r[i]-1;                }            }        }        printf("%lld\n",ans);        printf("%d %d\n", lans, rans);    }    return 0;}

 

UVALive 3517:Feel Good(单调栈 Grade C)