zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    用DECODE进行排序
    linux下批量替换文件内容
    Linux下chkconfig命令详解
    linux 命令参数列表过长以及find用法
    参数上使用自定义注解在aop中无法获取到该参数
    AOP
    AOP aspect XML 配置
    AOP前世与今生,aspect
    ETL工具之——kettle使用简介
    ETL工具之kittle使用案例整理
  • 原文地址:https://www.cnblogs.com/edmunds/p/13742244.html
Copyright © 2011-2022 走看看