• 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
    ":"%lld ",b[i]);
        }
        return 0;
    }
  • 相关阅读:
    Web 项目分页总结
    Hibernate配置JNDI数据源
    111
    南京信息工程大学实验报告(三)
    南京信息工程大学实验报告(四)
    南京信息工程大学实验报告(二)
    实验报告(一)
    第一次尝试发随笔
    【Selenium2+Python】常用操作
    【敏捷】敏捷下,各类文档砍砍砍?
  • 原文地址:https://www.cnblogs.com/luoyugongxi/p/12356639.html
Copyright © 2020-2023  润新知