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;
    }
  • 相关阅读:
    Linux防火墙管理(iptables)以及开放端口配置
    CSS 样式引入方式、常用选择器以及优先级权重的计算
    初识外边距合并-margin collapsing
    纯CSS实现自适应正方形
    常用正则
    vue 学习记录
    VScode 之快速创建vue模板
    vscode之常用插件
    工具函数
    Axios之配置参数
  • 原文地址:https://www.cnblogs.com/chen99/p/10771394.html
Copyright © 2011-2022 走看看