單調棧+線段樹

  •  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;
}
相關文章
相關標籤/搜索