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;
    }
  • 相关阅读:
    WPF程序设计 :第四章 按钮与其他控件(Buttons and Other Controls)
    C#参考 : 枚举类型
    C#3.0 新特性学习笔记(3):匿名类型
    F#语言2008年9月CTP版已经更新
    C#3.0 新特性学习笔记(1): 对象集合初始化器
    WPF程序设计基础:属性系统
    C#3.0 新特性学习笔记(2):var 隐式声明变量
    MSSql行列转换的Sql语法 详解与实例
    WPF程序设计 :第一章 应用程序和窗口(The Application and the Window)
    WPF程序设计 :第二章 基本画刷(Basic Brushes)
  • 原文地址:https://www.cnblogs.com/chen99/p/10771394.html
Copyright © 2011-2022 走看看