cf1313c2---单调栈+递推
题目链接:https://codeforces.com/contest/1313/problem/C2
题意:n层楼,每层高度不超过m[i],要求最终楼的高度满足:不存在i<j<k,ai>aj<ak。求满足这个要求的楼高度和的最大值
设dpl[i]表示第i个建成最高高度m[i],左边的满足条件的最大高度和。显然左边的高度都不能高于m[i],如果高于m[i]就把它建成m[i]即可。于是可以找左边第一个<=m[i]的数的位置l[i],则有dpl[i]=dpl[l[i]]+(i-l[i])*m[i]。对于右边的dpr[i]同理。最终最大高度和为max(dpl[i]+dpr[i]-m[i])。确定了最大高度和的对应位置之后,求出一组解就很方便了。找左(右)第一个<=m[i]的数可以用单调栈O(n)实现,递推也是O(n),总时间复杂度O(n)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5e5+10;
ll m[N],l[N],r[N],res[N],dpl[N],dpr[N],n,i,j;
stack<int> st;
int main(){
std::ios::sync_with_stdio(false);
cin>>n;
for (i=1;i<=n;i++) cin>>m[i];
m[0]=-1; m[n+1]=2e9; st.push(n+1);
for (i=n;i>=0;i--){
while (!st.empty()&&m[i]<=m[st.top()]){
l[st.top()]=i; st.pop();
}
st.push(i);
}
while (!st.empty()) st.pop();
m[n+1]=-1; m[0]=2e9; st.push(0);
for (i=1;i<=n+1;i++){
while (!st.empty()&&m[i]<=m[st.top()]){
r[st.top()]=i; st.pop();
}
st.push(i);
}
dpl[1]=m[1]; dpr[n]=m[n];
for (i=2;i<=n;i++) dpl[i]=dpl[l[i]]+(i-l[i])*m[i];
for (i=n-1;i>=1;i--) dpr[i]=dpr[r[i]]+(r[i]-i)*m[i];
int pos=0; ll ans=-1;
for (i=1;i<=n;i++)
if (dpl[i]+dpr[i]-m[i]>ans){
ans=dpl[i]+dpr[i]-m[i]; pos=i;
}
res[pos]=m[pos];
for (i=pos-1;i>=1;i--) res[i]=min(res[i+1],m[i]);
for (i=pos+1;i<=n;i++) res[i]=min(res[i-1],m[i]);
for (i=1;i<n;i++) cout<<res[i]<<' '; cout<<res[n];
return 0;
}

浙公网安备 33010602011771号