CodeForces547 B.Mike and Feet (单调栈/dp)

题意:

给定长度为n的数组, n<=2e5
定义F(l,r)为区间[l,r]的最小数,ans(k)为max(F(l,l+k-1)),其中1<=l<=n-k,即ans(k)长度为k的区间的F的最大值。
现在要求输出k依次为1到n的ans(k)值

思路:

用L(i)和R(i)记录以第i个数为最小值所能扩展的左右边界,则可以用a(i)去尝试更新ans(1)到ans(R(i)-L(i)+1),
因为在区间[L(i),R(i)]内包含a(i)的区间最小值都为a(i)。
先用每个a(i)更新ans(R(i)-L(i)+1),最后递推一下就行了:ans(i)=max(ans(i),ans(i+1)),理由同上(大区间包含小区间)。

计算L(i),R(i)很容易想到单调栈,dp也能写(见代码)。

code(dp):
#include<bits/stdc++.h>
using namespace std;
const int maxm=2e5+5;
int l[maxm],r[maxm];
int a[maxm];
int ans[maxm];
signed main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    a[0]=a[n+1]=-1;
    for(int i=1;i<=n;i++){
        int j=i-1;
        while(a[i]<=a[j])j=l[j];
        l[i]=j;
    }
    for(int i=n;i>=1;i--){
        int j=i+1;
        while(a[i]<=a[j])j=r[j];
        r[i]=j;
    }
    for(int i=1;i<=n;i++){
        l[i]++;
        r[i]--;
    }
    for(int i=1;i<=n;i++){
        int len=r[i]-l[i]+1;
        ans[len]=max(ans[len],a[i]);
    }
    for(int i=n-1;i>=1;i--){
        ans[i]=max(ans[i],ans[i+1]);
    }
    for(int i=1;i<=n;i++){
        cout<<ans[i]<<' ';
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值