CF 1484E. Skyline Photo

Skyline Photo

题意

\(n\) 座建筑排成一排,每座建筑都有 \(h_i\) 高度和 \(b_i\) 美丽度。现在把它们划分成几个连续的区间,每个区间的美丽度为这个区间最矮的建筑的美丽度,问所有区间的美丽度总和最大为多少。

\(1 \le n \le 3 \times 10^5, 1 \le h_i \le n, -10^9 \le b_i \le 10^9\)

分析

在从左往右遍历的时候,如果当前建筑的 \(h_i\) 小于前面的建筑,那么在之后不会再次用到前面建筑的高度(当前建筑可能用到)。

可以使用单调栈维护建筑的高度。

\(best_t\) 表示栈顶元素为 \(t\) 时,以 \(t\) 为结尾的那一段区间的最大值。

\(w_t\) 表示栈顶元素为 \(t\) 时,区间 \([1, t]\) 能划分的最大值。

\(dp_i\) 表示区间 \([1, i]\) 能划分的最大值。

Code

/* 终点是一切概率的结束,也是一切期望的开始 */
#include <bits/stdc++.h>
#define rep(i, x, y) for(int i = x; i <= y; i++)
#define int long long
using namespace std;
const int N = 300010, INF = 0x3f3f3f3f;

int h[N], b[N];
int stk[N], top;
int w[N], best[N];
int dp[N]; // 前i个建筑的最佳划分

void solve ()
{
    int n; cin >> n;
    rep(i, 1, n) cin >> h[i];
    rep(i, 1, n) cin >> b[i];
    top = 0;
    w[0] = -INF;
    rep(i, 1, n)
    {
        int t = dp[i-1];
        while (top && h[stk[top]] > h[i])
        {
            t = max(t, best[top]);
            top -- ;
        }
        stk[++ top] = i;
        best[top] = t;
        w[top] = max(w[top - 1], t + b[i]);
        dp[i] = w[top];
    }
    cout << dp[n] << endl;
}

signed main ()
{
    cout.tie(0)->sync_with_stdio(0);
    // int _; for (cin >> _; _--; )
        solve();
    return 0;
}
posted @ 2021-12-02 15:30  Horb7  阅读(41)  评论(0编辑  收藏  举报