寒假刷題38: Codeforces Round #622 (Div. 2) C2. Skyscrapers (hard version)

題目鏈接:

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

題目解析:

在C1中,我們讓每一個點作爲頂點,然後遍歷數組,這在C2中顯然會超時,現在考慮如何優化.

在遍歷的過程中,如果一個點可建造的高度h[i]大於等於當前可建造的最大高度maxhigh,顯然不用更新maxhigh.只有當h[i]<maxhigh,纔會把maxhigh更新爲a[i].也就是說,我們無需遍歷每一個點,只需要快速找到一個點左右兩邊第一個小於它的數.這顯然是單調棧問題

(真沒想到之前剛刷了幾道單調棧的題就派上用場了^_^)

AC代碼:

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXX = 500005;
ll h[MAXX],n;
ll ls[MAXX],rs[MAXX],sum[MAXX];
ll l[MAXX],r[MAXX];
ll ans[MAXX];
stack<int> s;
int main()
{
    cin >> n;
    for (int i=1; i<=n; i++)
    {
        cin >> h[i];
        sum[i] = sum[i-1] + h[i];
    }
    for (int i=1;i<=n; i++)
    {
        while(!s.empty() && h[s.top()] >= h[i]) s.pop();
        if (s.empty()) l[i] = 0;
        else l[i] = s.top();
        s.push(i);
    }
    while(!s.empty()) s.pop();
    for (int i=n; i; i--)
    {
        while(!s.empty() && h[s.top()] >= h[i]) s.pop();
        if (s.empty()) r[i] = n+1;
        else r[i] = s.top();
        s.push(i);
    }
    for (int i=1; i<=n; i++)
        ls[i] = ls[l[i]] + (i-l[i])*h[i];
    for (int i=n; ~i; i--)
        rs[i] = rs[r[i]] + (r[i]-i)*h[i];
    ll maxi = 0, maxv = -1;
    for (int i=1; i<=n; i++)
        if (ls[i]+rs[i]-h[i] > maxv)
            maxi = i, maxv = ls[i]+rs[i]-h[i];

    for (int i=maxi; i; i=l[i])
        for (int j=i; j>l[i]; j--) ans[j] = h[i];
    for (int i=maxi; i; i=r[i])
        for (int j=i; j<r[i]; ++j)
            ans[j] = h[i];
    for (int i=1; i<=n; i++)
        cout << ans[i] << ' ';
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章