线段树+单调栈+前缀和--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;
}

原文地址:https://www.cnblogs.com/shuizhidao/p/10780756.html