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

题目链接


题解思路:

利用单调栈去找出每一个位置 i 左边第一个高度小于它的位置 L 和右边第一个高度小于它的位置 R ,然后在区间 (L,i] 所能取到的最大值即为h[ i ],这段区间对整体的贡献就是 (i - L) * h[ i ],对右边做同样处理,最后我们只需要找到它整体最大的那个位置即可。


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
#define endl '
'
const int MAXN = 1e6+10;
const double EPS = 1e-12;
const ll mod = 1e9+7;

int n;
ll a[MAXN],l[MAXN],r[MAXN];
stack<int>st;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++){
        while(!st.empty()&&a[st.top()]>=a[i])st.pop();
        if(st.empty())l[i]=a[i]*i;
        else l[i]=l[st.top()]+a[i]*(i-st.top());
        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]=a[i]*(n-i+1);
        else r[i]=r[st.top()]+a[i]*(st.top()-i);
        st.push(i);
    }
    ll maxx=0,id=0;
    for(int i=1;i<=n;i++){
        if(l[i]+r[i]-a[i]>maxx){
            maxx=l[i]+r[i]-a[i];
            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]<<" ";
}
原文地址:https://www.cnblogs.com/Mmasker/p/12374087.html