Codeforces 1313 Skyscrapers (hard version) ( 单调栈 )

https://codeforces.com/contest/1313

满足题意的建造的摩天大厦是成“峰”状的,从左开始到最大值是单调递增,从最大值的位置到最右边是单调递减。

如何维护这个序列?用单调栈即可,类似用单调栈求长方形最大面积。

首先从左到右遍历一遍序列,维护一个递增单调栈,统计从左到右可建摩天楼楼层总数的最大值 rAns数组,然后从右往左遍历,维护一个单调递增栈,同样统计可建摩天楼层总数的最大值lAns 数组,最终再从1到n遍历一遍,取max(rAns+lAns - h[i]),因为多算了一遍第i个楼的高度

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 5e5+5;
 5 int h[maxn],n,top,pro[maxn];
 6 ll rAns[maxn],lAns[maxn];
 7 pair<int,int> stk[maxn]; 
 8 void mom_stk(ll ans[]){
 9     ll cur = 0;
10     top = 0;
11     stk[top] = {0,0};
12     for(int i = 1;i<=n;i++){
13         while(top>0 && stk[top].first > h[i]){
14             cur-=1ll*stk[top].first*(stk[top].second-stk[top-1].second);
15             top--;
16         }
17         cur+=1ll*h[i]*(i-stk[top].second);
18         stk[++top] = {h[i],i};
19         ans[i] = cur;
20     }
21 }
22 int main(){
23     scanf("%d",&n);
24     for(int i = 1;i<=n;i++) scanf("%d",&h[i]);
25     mom_stk(lAns);
26     reverse(h+1,h+1+n);
27     mom_stk(rAns);
28     reverse(rAns+1,rAns+n+1);
29     reverse(h+1,h+1+n);
30     int ansInd = 1;
31     ll res = rAns[1];
32     for(int i = 1;i<=n;i++){
33         ll cur = rAns[i] + lAns[i] - h[i];
34         if(cur > res) {
35             ansInd = i,  res = cur;
36         }
37     }
38     int skys[n+1];
39     skys[ansInd] = h[ansInd];
40     for(int i = ansInd - 1;i>=1;i--){
41         skys[i] = min(skys[i+1],h[i]);
42     }
43     for(int i = ansInd + 1;i<=n;i++){
44         skys[i] = min(skys[i-1],h[i]);
45     }
46     for(int i = 1;i<=n;i++){
47         printf("%d ",skys[i]);
48     }
49     return 0;
50 }
51 // 2 10 5 4 8
View Code

 

posted @ 2020-03-05 15:18  AaronChang  阅读(168)  评论(0编辑  收藏  举报