Codeforces Round #622 (Div. 2)C2

题意

N长度为500000以内,一个数字两边的数字不能都比他高,最多高一边

求他最大sum。叙述有问题,直接看样例

3

10 6 8

因为6左右都比他高,选择10 6 6或者6 6  8,sum明显前者高

所以答案输出10 6 6

思路:

求出每个a[i]左边(minl[i])和右边(minl[i])最近的一个比他小的数,用前缀和(suml) 和 后缀和(sumr)求得当a[i]是顶点时候sum=suml+sumr-a[i];

前缀和如果minl[i]==空集(0),那么suml[i]=i*a[i];如果minl[i]有位置,suml[i]=suml[minl[i]]+(i-minl[i])*a[i];

后缀和如果minr[i]==空集(n+1),那么sumr[i]=(n+1-i)*a[i];如果minr[i]有位置,sumr[i]=sumr[minr[i]]+(minr[i]-i)*a[i];

 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define mem(a,b) memset(a,b,sizeof(a))
#define modd 998244353
const int maxn=5e5+10;
int n;
ll a[maxn],b[maxn],minl[maxn],minr[maxn],suml[maxn],sumr[maxn];
stack<int>st;
int main(){
    scanf("%d",&n);
    for(it i=1;i<=n;i++){scanf("%lld",&a[i]);}
    for(it i=1;i<=n;i++){
        while(st.size()&&a[st.top()]>=a[i]){st.pop();}
        if(st.empty()){minl[i]=0;}
        else{minl[i]=st.top();}
        st.push(i);
    }
    while(st.size()){st.pop();}
    for(it i=n;i>=1;i--){
        while(st.size()&&a[st.top()]>=a[i]){st.pop();}
        if(st.empty()){minr[i]=n+1;}
        else{minr[i]=st.top();}
        st.push(i);
    }
    for(it i=1;i<=n;i++){
        if(!minl[i]){suml[i]=(ll)i*a[i];}
        else{
            suml[i]=suml[minl[i]]+(ll)(i-minl[i])*a[i];
        }
    }
    for(it i=n;i>=1;i--){
        if(minr[i]==n+1){sumr[i]=(ll)(minr[i]-i)*a[i];}
        else{
            sumr[i]=sumr[minr[i]]+(ll)(minr[i]-i)*a[i];
        }
    }
    ll ans=-1;int pos;
    for(it i=1;i<=n;i++){
        ll zz=sumr[i]+suml[i]-a[i];
        //cout<<sumr[i]<<" "<<minr[i]<<" "<<suml[i]<<endl;
        if(zz>ans){
            ans=zz,pos=i;
        }
    }

    b[pos]=a[pos];ll zhi=a[pos];
    for(it i=pos+1;i<=n;i++){
        if(a[i]<zhi){
            zhi=a[i];
        }
        b[i]=zhi;
    }
    zhi=a[pos];
    for(it i=pos-1;i>0;i--){
        if(a[i]<zhi){
            zhi=a[i];
        }
        b[i]=zhi;
    }
    for(it i=1;i<=n;i++){
        printf(i==n?"%lld\n":"%lld ",b[i]);
    }
    return 0;
}

 

posted @ 2020-02-24 13:40  ouluy  阅读(140)  评论(0编辑  收藏  举报