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 100010

int 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;
}

 

posted on 2014-09-29 11:08  ShineCheng  阅读(289)  评论(0编辑  收藏  举报

导航