题目链接:https://codeforces.ml/contest/1313/problem/C2
题目大意:
有n栋房子。每个房子的最高的高度b[i]应该在[1, a[i]]区间里。现在要满足不存在i<j<k有a[i]>a[j]<a[k]。并且要b[i]的和最大。输出b[i]-b[n]。方案可能不唯一。随便输出一个就可以。

思路:我们可以知道b[i]数组是一个单峰函数。并且最高的b[i]一定等于a[i]。
<mstyle displaystyle="false" scriptlevel="0"> f [ 0 [ [ i ] : a [ i ] 1 i 1 i b [ i ] </mstyle> <mstyle displaystyle="false" scriptlevel="0"> f [ 1 [ [ i ] : a [ i ] n i i n b [ i ] </mstyle> <mstyle displaystyle="false" scriptlevel="0"> f [ 0 ] [ i ] + f [ 1 ] [ i ] a [ i ] i 1 n b [ i ] </mstyle> <mstyle displaystyle="false" scriptlevel="0"> </mstyle> <mstyle displaystyle="false" scriptlevel="0"> </mstyle> <mstyle displaystyle="false" scriptlevel="0"> i f ( a [ i ] > a [ i 1 ] ) </mstyle> <mstyle displaystyle="false" scriptlevel="0"> f [ 0 ] [ i ] = f [ 0 ] [ i 1 ] + a [ i ] ; </mstyle> <mstyle displaystyle="false" scriptlevel="0"> </mstyle> <mstyle displaystyle="false" scriptlevel="0"> e l s e </mstyle> <mstyle displaystyle="false" scriptlevel="0"> f [ 0 ] [ i ] = f [ 0 ] [ l [ i ] ] + ( i l [ i ] ) a [ i ] ; </mstyle> <mstyle displaystyle="false" scriptlevel="0"> </mstyle> <mstyle displaystyle="false" scriptlevel="0"> f [ 1 ] [ i ] </mstyle> <mstyle displaystyle="false" scriptlevel="0"> l [ i ] : < = a [ i ] r [ i ] : < = a [ i ] </mstyle> <mstyle displaystyle="false" scriptlevel="0"> l [ i ] r [ i ] O ( N ) O ( N ) 线 O ( log n ) s e t O ( log n ) </mstyle> \begin{array}{l} f[0[[i]:a[i]为1-i单增时。\sum_{1}^{i}b[i]的最大值\\ f[1[[i]:a[i]为n-i单增时。\sum_{i}^{n}b[i]的最大值\\ 那么f[0][i]+f[1][i]-a[i]就是以第i处为最高点时\sum_{1}^{n}b[i]的最大值\\\\ 我们考虑状态转移方程:\\ if(a[i]>a[i-1]) \\f[0][i]=f[0][i-1]+a[i]; \\\\ else\\ f[0][i]=f[0][l[i]]+(i-l[i])*a[i];\\\\ f[1][i]的状态转移方程类似。\\ l[i]:左边第一个<=a[i]的坐标。r[i]:右边第一个<=a[i]的坐标\\ l[i]和r[i]可以用单调栈O(N)。分块O(\sqrt{N})。线段树O(\log{n})。setO(\log{n})求。 \end{array} f[0[[i]:a[i]1i1ib[i]f[1[[i]:a[i]niinb[i]f[0][i]+f[1][i]a[i]i1nb[i]if(a[i]>a[i1])f[0][i]=f[0][i1]+a[i];elsef[0][i]=f[0][l[i]]+(il[i])a[i];f[1][i]l[i]:<=a[i]r[i]:<=a[i]l[i]r[i]O(N)O(N )线O(logn)setO(logn)

#include<bits/stdc++.h>
#define LL long long
using namespace std;

LL a[500005], l[500005], r[500005];
LL f[2][500005], tot=0, g[500005];
struct node{
    LL x, i;
}q[500005];
int main(){

    int n;scanf("%d", &n);
    for(int i=1; i<=n; i++){
        scanf("%lld", &a[i]);
    }
    //单调栈
    for(int i=1; i<=n; i++){
        if(tot==0||q[tot].x<a[i]){
            q[++tot]={a[i], i};
        }
        while(tot!=0&&q[tot].x>=a[i]){
            l[q[tot].i]=q[tot-1].i;
            r[q[tot].i]=i;
            tot--;
        }
        q[++tot]={a[i], i};
    }
    while(tot){
        l[q[tot].i]=q[tot-1].i;
        r[q[tot].i]=n+1;
        tot--;
    }
    //dp
    for(int i=1; i<=n; i++){
        if(a[i]>a[i-1]){
            f[0][i]=f[0][i-1]+a[i];
        }
        else{
            f[0][i]=f[0][l[i]]+(i-l[i])*a[i];
        }
    }
    for(int i=n; i>=1; i--){
        if(a[i]>a[i+1]){
            f[1][i]=f[1][i+1]+a[i];
        }
        else{
            f[1][i]=f[1][r[i]]+(r[i]-i)*a[i];
        }
    }
    //方案
    LL mx=0, pos=0, now=0;
    for(int i=1; i<=n; i++){
        if(f[0][i]+f[1][i]-a[i]>mx){
            mx=f[0][i]+f[1][i]-a[i];
            pos=i;
        }
    }
    g[pos]=a[pos], now=a[pos];
    for(int i=pos+1; i<=n; i++){
        if(a[i]>=now){
            g[i]=now;
        }
        else{
            g[i]=a[i];
            now=g[i];
        }
    }
    now=a[pos];
    for(int i=pos-1; i>=1; i--){
        if(a[i]>=now){
            g[i]=now;
        }
        else{
            g[i]=a[i];
            now=g[i];
        }
    }
    for(int i=1; i<=n; i++){
        printf("%lld ", g[i]);
    }

    return 0;
}