题意: 给了一堆楼 要求 不能存在 i < j < k 时, 出现 a i a_i ai > a j a_j aj < a k a_k ak 的情况 不一定非要挨着 楼高有限制 不得超过 m i m_i mi

官方题解是

单调栈 正着一遍 反着一遍就可以了
正着:dp[i]前i个保持递增序列的最大前缀和
反着就递减的最大后缀和
然后on扫最大

我的ST表 + (贪心)分治

找到最小值 要么左边全是最小值 要不就是右边
选择 一个 ( r m i n s . s e c o n d ) m i n s . f i r s t + s 1 + m i n s . f i r s t (r - mins.second) * mins.first + s1 + mins.first (rmins.second)mins.first+s1+mins.first ( m i n s . s e c o n d l ) m i n s . f i r s t + s 2 + m i n s . f i r s t (mins.second - l) * mins.first + s2 + mins.first (mins.secondl)mins.first+s2+mins.first 一个比较大的固定 贪心的选取它 接着分治另一边
由于最小的已经固定 所以另一边不考虑固定边可能会影响

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 5e5 + 5;

int lg[maxn];
int a[maxn], b[maxn];
pair<int, int> f[maxn][30];
int n, m;

void ST_build() {
    for(int i = 1; i <= n; i ++ ) f[i][0] = make_pair(a[i], i);
    int t = (lg[n]-1)/(lg[2]-1) + 1;
    for(int j = 1; j < t; j ++ ) {
        for(int i = 1; i <= n - (1 << j) + 1; i ++ ) {
            f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
        }
    }
}

pair<int, int> ST_query(int l, int r){
    int k = (lg[r - l + 1] - 1);
    return min(f[l][k], f[r - (1 << k) + 1][k]);
}

int solve(int l, int r) {
	if(l > r) return 0;
	if(l == r) return b[l] = a[l];
	pair<int, int> mins = ST_query(l, r);
	int s1 = solve(l, mins.second - 1);
	int s2 = solve(mins.second + 1, r);
	if((r - mins.second) * mins.first + s1 > (mins.second - l) * mins.first + s2) {
		for(int i = mins.second; i <= r; i ++) b[i] = mins.first;
		return (r - mins.second) * mins.first + s1 + mins.first;
	} else {
		for(int i = l; i <= mins.second; i ++) b[i] = mins.first;
		return (mins.second - l) * mins.first + s2 + mins.first;
	}
}

signed main() {
	ios::sync_with_stdio(false), cin.tie(0);
	memset(f, 0x3f, sizeof(f));
	for(int i = 1; i < maxn; i ++){
        lg[i] = lg[i - 1] + ((1 << lg[i - 1]) == i);
    }
	cin >> n;
	for(int i = 1; i <= n; i ++) cin >> a[i];
	ST_build();
	solve(1, n);
	for(int i = 1; i <= n; i ++) cout << b[i] << " ";
	return 0;
}