• Codeforces Round #622 (Div. 2) C2. Skyscrapers (hard version)(单调栈,递推)


    Codeforces Round #622 (Div. 2) C2. Skyscrapers (hard version)

    题意:

    你是一名建筑工程师,现给出 n 幢建筑的预计建设高度,你想建成峰状,如:

     1 2 3 2 1 → 1 2 3 2 1 

     1 2 3 1 2 → 1 2 3 1 1 

     8 10 6 → 8 10 6 

     10 6 8 → 10 6 6 

    问所有建筑的高度和最大为多少。

    思路:

    单调递增栈栈顶存储以当前点为峰的单侧最低高度下标,另存储以每个点为峰的左右最大高度和。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int M = 550000;
    
    ll a[M], l[M], r[M];
    
    int main()
    {
        int n; cin >> n;
        for (int i = 1; i <= n; i++) cin >> a[i];
    
        stack<int> st;
    
        for (int i = 1; i <= n; i++)//递推每个点左侧的最大高度和
        {
            while (!st.empty() && a[st.top()] >= a[i]) st.pop();
            if (st.empty()) l[i] = i * a[i];
            else l[i] = l[st.top()] + (i - st.top()) * a[i];
            st.push(i);
        }
    
        while (!st.empty()) st.pop();
    
        for (int i = n; i >= 1; i--)//递推每个点右侧的最大高度和
        {
            while (!st.empty() && a[st.top()] >= a[i]) st.pop();
            if (st.empty()) r[i] = (n - i + 1) * a[i];
            else r[i] = r[st.top()] + (st.top() - i) * a[i];
            st.push(i);
        }
    
        ll res = 0, id = 0;
        for (int i = 1; i <= n; i++)//寻找最大高度和的峰点
        {
            ll tmp = l[i] + r[i] - a[i];
            if (tmp > res) { res = tmp; id = i; }
        }
    
        for (int i = id - 1; i >= 1; i--) a[i] = min(a[i], a[i + 1]);//摊平峰左侧
        for (int i = id + 1; i <= n; i++) a[i] = min(a[i], a[i - 1]);//摊平峰右侧
    
        for (int i = 1; i <= n; i++) cout << a[i] << " ";
    
        return 0;
    }

    代码参考自:knight_wang

  • 相关阅读:
    IO多路复用 IO异步
    你没听说过的协程
    事件驱动和IO操作
    堡垒机前戏——paramiko
    听说过的多进程,多线程到底是什么鬼
    socket套接字
    看见就烦的异常
    struts2值栈内部数据结构详解
    hibernate一级缓存的源码初窥
    使用自定义标签模拟jstl的<c:for each>标签
  • 原文地址:https://www.cnblogs.com/Kanoon/p/12527089.html
Copyright © 2020-2023  润新知