zoukankan      html  css  js  c++  java
  • 南昌邀请赛I.Max answer 单调栈+线段树

    题目链接:https://nanti.jisuanke.com/t/38228

    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(1n5×105).

    Second line contains nn integers represent the array a (105ai105).

    Output

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

    样例输入

    5
    1 2 3 4 5

    样例输出

    36

    题目定义区间的值为区间之和乘以区间的最小值,要你求出最大的区间值
    求出前缀和sum并用线段树维护,再用单调栈求出第i个点之前第一个比他小的点l[i](下标),以及i之后第一个比他小的点r[i](下标)
    枚举每个点,如果第i个点非负,区间值即为(sum[r[i]]-sum[l[i]-1])*a[i]
    如果第i个点为负数则在[l[i],r[i]]内找到最小的区间和并乘以a[i]即为区间值
    #include<iostream>
    #include<stack>
    using namespace std;
    #define maxn 500005
    #define ls l,mid,rt<<1
    #define rs mid+1,r,rt<<1|1
    #define ll long long
    #define inf 0x3f3f3f3f
    int n,l[maxn],r[maxn];
    ll a[maxn],b[maxn],pre[maxn],sum[2][maxn<<2];
    void pushup(int rt)
    {
        sum[0][rt]=max(sum[0][rt<<1],sum[0][rt<<1|1]);
        sum[1][rt]=min(sum[1][rt<<1],sum[1][rt<<1|1]);
    }
    void build(int l,int r,int rt)
    {
        if(l==r)
        {
            sum[0][rt]=sum[1][rt]=pre[l];
            return ;
        }
        int mid=l+r>>1;
        build(ls);
        build(rs);
        pushup(rt);
    }
    ll q1(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&R>=r)return sum[0][rt];
        int mid=l+r>>1;
        ll ans=-inf;
        if(L<=mid)ans=max(ans,q1(L,R,ls));
        if(R>mid)ans=max(ans,q1(L,R,rs));
        return ans;
    }
    ll q2(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&R>=r)return sum[1][rt];
        int mid=l+r>>1;
        ll ans=inf;
        if(L<=mid)ans=min(ans,q2(L,R,ls));
        if(R>mid)ans=min(ans,q2(L,R,rs));
        return ans;
    }
    int main()
    {
        cin>>n;
        pre[0]=0;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            pre[i]=pre[i-1]+a[i];
        }
        build(1,n,1);
        stack<int>s;
        for(int i=1;i<=n;i++)
        {
            while(s.size()&&a[s.top()]>=a[i])s.pop();
            if(s.empty())l[i]=1;
            else l[i]=s.top()+1;
            s.push(i);
        }
        while(!s.empty())s.pop();
        for(int i=n;i>=1;i--)
        {
            while(s.size()&&a[s.top()]>=a[i])s.pop();
            if(s.empty())r[i]=n;
            else r[i]=s.top()-1;
            s.push(i);
        }
        ll ans=-inf;
        for(int i=1;i<=n;i++)
        {
            if(a[i]>=0)ans=max(ans,(pre[r[i]]-pre[l[i]-1])*a[i]);
            else
            {
                ll maxx,minn;//maxx为[l[i]-1,i-1]的最大前缀和,minn为[i,r[i]]的最小前缀和,最小减最大负的就最多 
                maxx=q1(max(l[i]-1,1),max(i-1,l[i]),1,n,1);
                minn=q2(i,r[i],1,n,1);
                ans=max(ans,(minn-maxx)*a[i]);
            }
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    HttpService与WebService的差异
    在oracle中varchar和varchar2有什么区别?
    物联网项目的思考
    配置JDK-Java运行环境
    浅谈DDD
    参数化SQL语句
    OneNote无法同时设置中英文字体设置解决办法
    Oracle OCI-22053:溢出错误解决方法
    oracle 日期格式
    Visual Studio 2017各版本安装包离线下载
  • 原文地址:https://www.cnblogs.com/chen99/p/10771394.html
Copyright © 2011-2022 走看看