• 线段树+单调栈+前缀和--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;
    }
    
    
  • 相关阅读:
    AFNetwork 作用和用法详解
    ios 常见错误记录
    UIView的setNeedsLayout, layoutIfNeeded 和 layoutSubviews 方法之间的关系解释
    AutoLayout
    矩阵的法式
    极小多项式
    对角化
    线性映射
    线性方程组的解
    特征值和特征向量
  • 原文地址:https://www.cnblogs.com/shuizhidao/p/10780756.html
Copyright © 2020-2023  润新知