Codeforces 319B Psychos in a Line 题解 [ 绿 ] [ 单调栈 ] [ 动态规划 ] [ adhoc ]

Psychos in a Line:很好的单调栈优化 dp 题!

观察

我们先观察,一个精神病人会一直杀到什么时候。显然,会杀到右边第一个比他大的精神病人那里,然后他就杀不动了。

因此我们可以从右往左考虑,算出左边的精神病人杀掉这个精神病人后左边的人的答案是什么。假设左边的人目前已经刀了 x 个人,被杀的人目前会y 个人。如果左边杀这个人的时候这个人该杀的还没杀完,那么左边人就要接着这个人继续把该杀的杀掉,又因为它们刀人是同步进行的,所以此时左边的人目前刀掉的人数取 max(y,x+1)

于是,我们定义 dpi 表示第 i 个人目前会刀几个人,然后 O(n2) 转移即可。

优化

但是这样显然无法通过,考虑如何优化。

因为一个人会被他左边第一个比他大的人杀掉(不一定最后真的是被他杀的,如果他杀这个人之前就被杀了,那么情况还是等价的,不影响计算),所以我们从右到左维护一个单调栈,维护右边的最大值。在一个元素入栈的时候,只取弹出的元素转移即可。

时间复杂度 O(n),主要还是理解一个人先钦定被左边第一个比他大的人杀,之后再动态调整,不影响最终答案的类似反悔贪心的思想

代码

#include <bits/stdc++.h>
using namespace std;
int n,a[100005],dp[100005],tp=0,s[100005],ans;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=n;i>=1;i--)
    {
        int res=0;
        while(tp&&a[s[tp]]<a[i])res=max(res+1,dp[s[tp--]]);
        s[++tp]=i;
        dp[i]=res;
        ans=max(dp[i],ans);
    }
    cout<<ans;
    return 0;
}
posted @   KS_Fszha  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示