Max answer(单调栈,rmq)

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 \times 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≤ai​≤105).

Output

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

样例输入复制

5
1 2 3 4 5

样例输出复制

36

题意:

求最大的 区间和*区间最小值.(区间内有负数)

解析:

我们把整数部分和负数部分分开求

整数部分:只能是全为整数的区间,就是求矩形最大面积,经典单调栈题目

负数部分:遍历每一个负数a[i]

将区间扩至最大(扩至和最小),然后sum*a[i],贪心一下

扩区间方法:

求出前缀和,后缀和,然后查询a[i]的左边最小的,减去a[i]~a[n],比较是否大于0,判断是否需要往左边扩

查询最小值用rmq算法

总复杂度是O(nlogn)

ac:

#include<bits/stdc++.h>
#define ll long long
#define maxx 500005
using namespace std;

ll str[maxx];
ll minn[maxx][21],minn2[maxx][21];
ll arr[maxx],brr[maxx];
ll a[maxx];

struct node
{
    ll num,pre,next;
    ll k;
};

ll solve(ll n)
{
    stack<node> Q;
    node tmp;
    ll ans=-999999999999,sum=-999999999999,num;
    str[0]=0;
    for(ll i=1;i<=n;i++)
    {
        if(i==1)
            str[i]=a[i];
        else
            str[i]=str[i-1]+a[i];
    }
    tmp.num=a[1];
    tmp.pre=1;
    tmp.next=1;
    tmp.k=1;
    Q.push(tmp);
    ll x=0,y=0;
    for(ll i=2;i<=n;i++)
    {
        node tmp1;
        tmp1.num=a[i];
        tmp1.pre=tmp1.next=1;
        tmp1.k=i;
        while(!Q.empty()&&tmp1.num<=Q.top().num)
        {
            tmp=Q.top();
            Q.pop();
            if(!Q.empty())
            Q.top().next+=tmp.next;
            tmp1.pre+=tmp.pre;
            ans=tmp.num*(str[tmp.k+tmp.next-1]-str[tmp.k-tmp.pre]);
            if(ans>=sum)
                sum=ans;
        }
        Q.push(tmp1);
    }
    while(!Q.empty())
    {
        tmp=Q.top();
        Q.pop();
        if(!Q.empty())
        Q.top().next+=tmp.next;
        ans=tmp.num*(str[tmp.k+tmp.next-1]-str[tmp.k-tmp.pre]);
        if(ans>=sum)
            sum=ans;
    }
    return sum;
}

void getbestarr(ll n)
{
    ll tem = (ll)floor(log2((double)n));
    for(ll i=1;i<=n;i++)
        minn[i][0]=arr[i];
    for(ll j=1;j<=tem;j++)
    {
        for(ll i=1;i+(1<<j)-1<=n;i++)
            minn[i][j] = min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]);
    }
}

ll query(ll a,ll b)
{
    ll k = log2(b-a+1);
    return min(minn[a][k],minn[b-(1<<k)+1][k]);
}

void getbestarr2(ll n)
{
    ll tem = (ll)floor(log2((double)n));
    for(ll i=1;i<=n;i++)
        minn2[i][0]=brr[i];
    for(ll j=1;j<=tem;j++)
    {
        for(ll i=1;i+(1<<j)-1<=n;i++)
            minn2[i][j] = min(minn2[i][j-1],minn2[i+(1<<(j-1))][j-1]);
    }
}

ll query2(ll a,ll b)
{
    ll k = log2(b-a+1);
    return min(minn2[a][k],minn2[b-(1<<k)+1][k]);
}

int main()
{
    ll n;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);

    for(int i=1;i<=n;i++)
        arr[i]=arr[i-1]+a[i];
    for(int i=n;i>=1;i--)
        brr[i]=brr[i+1]+a[i];
    getbestarr(n);
    getbestarr2(n);
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]<0)
        {
            ll sum=a[i];
            if(i<n)
            {
                ll dd=query(i+1,n);
                if(dd<arr[i])
                    sum+=dd-arr[i];
            }
            if(i>1)
            {
                ll cc=query2(1,i-1);
                if(cc<brr[i])
                    sum+=cc-brr[i];
            }
            ans=max(ans,sum*a[i]);
        }
    }
    ans=max(ans,solve(n));
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_41183791/article/details/89431494