CF1313C2 Skyscrapers (hard version) -单调栈优化dp

给定一个数组A,构造一个数组B,满足,B先增再减(或者只增,只减), 且 bi <= ai
使得∑bi最大

#include <algorithm>
#include <vector>
#include <stack>
#define ll long long
#define PII pair<int, int>
#define FOR(i, s, e) for (int i = s; i <= e;i++)
#define ROF(i, e, s) for (int i = e; i >= s;i--)
#define debug(a) cout << #a << "=" << a << endl;
#define pb(a) push_back(a)
#define endl '\n'
#define INF 0x3f3f3f3f
#define LNF 0x3f3f3f3f3f3f3f3f 
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 7;
void init_code(){
	#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
	#endif
}


ll a[N],n;
int nex[N],prv[N];
ll f[N],fl[N],fr[N];
void NLE(){
	a[0]=-INF,a[n+1]=-INF;  // 设置默认值
	stack<int>st;
	//求nxt
	FOR(i,1,n+1){
		while(!st.empty() && a[st.top()]>a[i]){
			nex[st.top()]=i; st.pop();
		}   st.push(i);
	}	st.pop();
	//求prv
	ROF(i,n,0){
		while(!st.empty() && a[st.top()]>a[i]){
			prv[st.top()]=i; st.pop();
		}   st.push(i);
	}	st.pop();
}

int main(int argc, char const *argv[])
{	
	init_code();
	cin>>n;
	FOR(i,1,n)cin>>a[i];

	// 求nxt,prv数组
	NLE();   
	//dp
	FOR(i,1,n){ int j=prv[i]; fl[i]=a[i]*(i-j) + fl[j]; }
	ROF(i,n,1){ int j=nex[i]; fr[i]=a[i]*(j-i) + fr[j]; }
	FOR(i,1,n){ f[i]=fl[i]+fr[i]-a[i]; }
	//求具体方案
	int id=max_element(f+1,f+1+n)-f;
	ROF(i,id-1,1)a[i]=min(a[i],a[i+1]);
	FOR(i,id+1,n)a[i]=min(a[i],a[i-1]);
	FOR(i,1,n){ cout<<a[i]<<" "; }
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值