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;
}

  

原文地址:https://www.cnblogs.com/edmunds/p/13742244.html