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