单调栈+线段树

  •  262144K
 

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.html

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

Input

First line contains an integer n(1 \le n \le 5 \times 10 ^5n(1n5×105).ui

Second line contains nn integers represent the array a (-10^5 \le a_i \le 10^5)a(105ai105).spa

Output

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

样例输入

5
1 2 3 4 5

样例输出

36

陈你blog

题意 : 给你 n 个元素,有正有负,要求你去寻找一个区间,要求区间中最小的元素乘以此元素所在的一段区间的和要最大,输出最大值ip

思路分析:内存

  若元素全为正,显然就是单调栈的入门题了,可是如今元素有负的,所以须要换个角度去考虑ci

  借助单调栈,咱们能够找到每一个元素做为最小值所在的区间get

  假设如今选取的一个元素是负的,那么咱们是不就要找一段负的区间的和最小,乘起来才会使最大

  那么这个时候就能够借助前缀和,该位置右边的最小值减去左边的最大值便可,若左边最大值小于0,此时就不要减去

  用线段树去维护

  一直有个地方写错,就是单调栈找每一个元素所在区间的地方

 

代码示例:

#define ll long long
const ll maxn = 5e5+5;
const ll mod = 1e9+7;
const double eps = 1e-9;
const double pi = acos(-1.0);
const ll inf = 0x3f3f3f3f;

ll n;
ll a[maxn];
ll lf[maxn], rf[maxn];
struct pp
{
    ll num, id;
};
struct pp sta[maxn];

struct node
{
    ll l, r;
    ll mm, mi;
}t[maxn<<2];
#define lson k<<1
#define rson k<<1|1
ll sum[maxn];
void init(){
    ll top = 0;
    
    a[n+1] = -999999999;
    for(ll i = 1; i <= n+1; i++){
        while(top > 0 && sta[top].num > a[i]){
            rf[sta[top].id] = i-1;
            top--; 
        }
        sta[++top] = {a[i], i};
    }
    top = 0; 
    for(ll i = 1; i <= n+1; i++){
        ll pos = i;
        while(top > 0 && sta[top].num > a[i]){
            pos = sta[top].id;
            top--;
        }
        sta[++top] = {a[i], pos};
        lf[i] = pos;
    } 
}

void build(ll l, ll r, ll k){
    t[k].l = l, t[k].r = r;
    if (l == r){
        t[k].mm = t[k].mi = sum[l];
        return;
    }
    ll mid = (l+r)>>1;
    build(l, mid, lson);
    build(mid+1, r, rson);
    t[k].mm = max(t[lson].mm, t[rson].mm);
    t[k].mi = min(t[lson].mi, t[rson].mi);
}

ll qmax(ll l, ll r, ll k){
    ll ans = -1e18;
    if (l <= t[k].l && t[k].r <= r) {
        return t[k].mm;
    }
    ll mid = (t[k].l+t[k].r)>>1;
    if (l <= mid) ans = max(ans, qmax(l, r, lson));
    if (r > mid) ans = max(ans, qmax(l, r, rson));
    return ans;
}

ll qmin(ll l, ll r, ll k){
    ll ans = 1e18;
    if (l <= t[k].l && t[k].r <= r) {
        return t[k].mi;
    }
    ll mid = (t[k].l+t[k].r)>>1;
    if (l <= mid) ans = min(ans, qmin(l, r, lson));
    if (r > mid) ans = min(ans, qmin(l, r, rson));
    return ans;
}


void solve(){
    for(ll i = 1; i <= n; i++){
        sum[i] = sum[i-1]+a[i];
    }
    ll ans = 0;
    build(1, n, 1);
    for(ll i = 1; i <= n; i++){
        if (a[i]>0) ans = max(ans, (sum[rf[i]]-sum[lf[i]-1])*a[i]);
        else {
            ans = max(ans, a[i]*(qmin(i, rf[i], 1ll)-max(qmax(lf[i], i, 1ll), 0ll)));
        }
    }
    printf("%lld\n", ans);
}

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    cin >> n;
    for(ll i = 1; i <= n; i++){
        scanf("%lld", &a[i]);
    }    
    init();
    solve();
    return 0;
}
相关文章
相关标签/搜索