• 「题解」洛谷 UVA1619 感觉不错 Feel Good


    题目

    UVA1619 感觉不错 Feel Good

    简化题意

    找一段区间使得这段区间的最小值乘这段区间的元素和最大,在保证最大的前提下保证区间最短,在以上前提下保证左端点最小。

    思路

    单调栈,悬线法。

    在最小值确定的情况下区间越长越好(除了最小值是 (0)

    Code

    悬线法:

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #define M 100001
    
    typedef long long ll;
    
    ll ans, left, right, sum[M];
    int n, l[M], r[M], a[M];
    
    inline void read(int &T) {
        int x = 0;
        bool f = 0;
        char c = getchar();
        while (c < '0' || c > '9') {
            if (c == '-') f = !f;
            c = getchar();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = getchar();
        }
        T = f ? -x : x;
    }
    
    int main() {
        int cnt = 0;
        while (1) {
            if (!cnt) scanf("%d", &n);
            ++cnt, ans = 0;
            memset(sum, 0, sizeof sum);
            for (int i = 1; i <= n; ++i) {
                read(a[i]);
                sum[i] = sum[i - 1] + a[i];
                l[i] = r[i] = i;
            }
            for (int i = 1; i <= n; ++i) {
                while (l[i] > 1 && a[i] <= a[l[i] - 1]) l[i] = l[l[i] - 1];
            }
            for (int i = n; i >= 1; --i) {
                while (r[i] < n && a[i] <= a[r[i] + 1]) r[i] = r[r[i] + 1];
            }
            for (int i = 1; i <= n; ++i) {
                if (a[i] == 0) l[i] = r[i] = i;
                if ((sum[r[i]] - sum[l[i] - 1]) * 1ll * a[i] > ans) {
                    ans = (sum[r[i]] - sum[l[i] - 1]) * 1ll * a[i];
                    right = r[i], left = l[i];
                }
                if ((sum[r[i]] - sum[l[i] - 1]) * 1ll * a[i] == ans) {
                    if (r[i] - l[i] < right - left) {
                        right = r[i], left = l[i];
                    }
                }
            }
            printf("%lld
    ", ans);
            printf("%lld %lld
    ", left, right);
            if (scanf("%d", &n) == EOF || !n) break;
            puts("");
        }
        return 0;
    }
    

    单调栈:

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #define M 100002
    
    typedef long long ll;
    
    ll ans, left, right, sum[M];
    int n, top, s[M], w[M], a[M];
    
    inline void read(int &T) {
        int x = 0;
        bool f = 0;
        char c = getchar();
        while (c < '0' || c > '9') {
            if (c == '-') f = !f;
            c = getchar();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = getchar();
        }
        T = f ? -x : x;
    }
    
    int main() {
        int cnt = 0;
        while (1) {
            if (!cnt) scanf("%d", &n);
            ++cnt, ans = -1, left = 0, right = 0, top = 0;
            memset(sum, 0, sizeof sum);
            for (int i = 1; i <= n; ++i) {
                read(a[i]);
                sum[i] = sum[i - 1] + a[i];
            }
            a[n + 1] = 0, s[++top] = 1, w[top] = 1;
            for (int i = 2; i <= n + 1; ++i) {
                if (a[s[top]] < a[i]) {
                    s[++top] = i;
                    w[top] = 1;
                }
                else {
                    int len = 0;
                    while (top && a[s[top]] >= a[i]) {
                        len += w[top];
                        int r = i - 1, l = r + 1 - len;
                        if (a[s[top]] == 0) r = s[top], l = s[top];
                        if (1ll * (sum[r] - sum[l - 1]) * a[s[top]] > ans) {
                            ans = 1ll * (sum[r] - sum[l - 1]) * a[s[top]];
                            right = r, left = l;
                        }
                        if (1ll * (sum[r] - sum[l - 1]) * a[s[top]] == ans) {
                            if (l < left && len <= right - left + 1) {
                                right = r, left = l;
                            }
                        }
                        --top;
                    }
                    s[++top] = i, w[top] = len + 1;
                }
            }
            printf("%lld
    ", ans);
            printf("%lld %lld
    ", left, right);
            if (scanf("%d", &n) == EOF || !n) break;
            puts("");
        }
        return 0;
    }
    
  • 相关阅读:
    Java基础语法
    C语言练习题目
    C语言进阶(1)
    C语言易错点
    SQL语句入门
    C语言算法基础
    C语言算法入门
    嵌入式入门
    C语言基础(3)
    C语言基础(2)
  • 原文地址:https://www.cnblogs.com/poi-bolg-poi/p/13650405.html
Copyright © 2020-2023  润新知