• 线段树+单调栈+前缀和--2019icpc南昌网络赛I


    线段树+单调栈+前缀和--2019icpc南昌网络赛I

    Alice has a magic array. She suggests that the value of a interval is equal to the sum of the values in the interval, multiplied by the smallest value in the interval.

    Now she is planning to find the max value of the intervals in her array. Can you help her?

    Input

    First line contains an integer n(1 le n le 5 imes 10 ^5n(1≤n≤5×105).

    Second line contains nn integers represent the array a (-10^5 le a_i le 10^5)a(−105≤a**i≤105).

    Output

    One line contains an integer represent the answer of the array.

    样例输入复制

    5
    1 2 3 4 5
    

    样例输出复制

    36
    

    思路

    算前缀和,以每个a_i为最低点,用单调栈求出a_i的所能影响的范围

    若a_i>=0,则maxR-minL

    若a_i<0,则minR-min(0,maxL)

    minR,和maxL用线段树查询,线段树构建:以前缀和为底,找出范围内的最值

    代码

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <cmath>
    #include <sstream>
    #include <algorithm>
    #include <set>
    #include <map>
    #include <vector>
    #include <queue>
    #include <iomanip>
    #include <stack>
    
    using namespace std;
    
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    const int N = 5e5+5;
    const int MOD = 1e9 + 9;
    const double pi = 3.1415926;
    
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    #define F(i, l, r) for(int i = l;i <= (r);++i)
    #define RF(i, l, r) for(int i = l;i >= (r);--i)
    
    LL a[N], sum[N], tree_min[N << 2], tree_max[N << 2];
    void build(int l, int r, int rt)
    {
    
        if(l == r)
        {
            tree_min[rt] = tree_max[rt] = sum[l];
            return ;
        }
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        tree_max[rt] = max(tree_max[rt << 1], tree_max[rt << 1 | 1]);
        tree_min[rt] = min(tree_min[rt << 1], tree_min[rt << 1 | 1]);
    }
    
    LL Query_max(int L, int R, int l, int r, int rt)
    {
        if(L <= l && r <= R)
            return tree_max[rt];
        int m = (l + r) >> 1;
        LL ans = -1e18;
        if(L <= m)
            ans = max(ans, Query_max(L, R, lson));
        if(R > m)
            ans = max(ans, Query_max(L, R, rson));
        return ans;
    }
    
    LL Query_min(int L, int R, int l, int r, int rt)
    {
        if(L <= l && r <= R)
            return tree_min[rt];
        int m = (l + r) >> 1;
        LL ans = INF;
        if(L <= m)
            ans = min(ans, Query_min(L, R, lson));
        if(R > m)
            ans = min(ans, Query_min(L, R, rson));
        return ans;
    }
    
    stack<int> s;
    LL rig[N], lef[N];
    int main()
    {
        int n;
        cin >> n;
        F(i, 1, n)
        {
            cin >> a[i];
            sum[i] = sum[i - 1] + a[i];
        }
        build(1, n, 1);
        F(i, 1, n)
        {
            while(!s.empty() && a[s.top()] > a[i]) {rig[s.top()] = i - 1;s.pop();}
            s.push(i);
        }
        while(!s.empty())
        {
            rig[s.top()] = n;
            s.pop();
        }
        RF(i, n, 1)
        {
            while(!s.empty() && a[s.top()] > a[i]) {lef[s.top()] = i + 1;s.pop();}
            s.push(i);
        }
        while(!s.empty())
        {
            lef[s.top()] = 1;
            s.pop();
        }
        LL ans = -1e18, t;
        F(i, 1, n)
        {
            if(a[i] > 0)
                t = sum[rig[i]] - sum[lef[i] - 1];
            else
                t = Query_min(i, rig[i], 1, n, 1) - max(0ll, Query_max(lef[i], i, 1, n, 1));
            //cout << Query_min(i, rig[i], 1, n, 1) << " " << max(0ll, Query_max(lef[i], i, 1, n, 1)) << endl;
            ans = max(ans, t * a[i]);
        }
        cout << ans << endl;
        return 0;
    }
    
    
  • 相关阅读:
    新博客第一篇,字符串 Unicode 转义
    C# 泛型方法的类型推断
    一个改进 LRU 算法的缓冲池 update 2013.7.15
    C# 判断类型间能否隐式或强制类型转换,以及开放泛型类型转换 update 2015.02.03
    C# 词法分析器(三)正则表达式
    java面试题(二)
    Map的迭代
    Spring aop切面插入事物回滚
    Log4J的配置
    js中将yyyyMMdd格式的日期转换
  • 原文地址:https://www.cnblogs.com/shuizhidao/p/10780756.html
Copyright © 2020-2023  润新知