首页 > 其他 > 详细

琪露诺 双端队列优化转移方程

时间:2019-06-01 17:38:18      阅读:52      评论:0      收藏:0      [点我收藏+]

众所周知,琪露诺是以笨蛋闻名的冰之妖精。

题目:https://www.luogu.org/problemnew/show/P1725

 

显然,是一道DP题(很恶心显然二字,现在来恶心你们)

 

状态转移是dp[i]=max(dp[k])+a[i];

跳到当前位置的最大值是前面能跳到到这里的所有位置的最大值加上当前位置的冰冻值;

为什么要用双端队列呢(因为爽啊)

这个很裸了已经,滑动窗口的思想。就是纯DP是会T的,所以我们寻找最大值时要优化时间;

如果当前的值比队列中的值大,就把队列中的已有元素弹出(因为我们是从前往后遍历的,一个位置在前且值小的元素是不会做出任何贡献的);

代码

#include<cstdio>
#include<cstring>
#include<deque>
#include<algorithm>
using namespace std;
const int maxn=200100;
struct node
{
    int val;//DP最大值 
    int num;//
};

int n,a[maxn],l,r;
int dp[maxn];
deque <node> s;
int main()
{
    scanf("%d%d%d",&n,&l,&r);
    for(int i=0;i<=n;i++)
    {
        scanf("%d",a+i);
    }
    int tail=0;dp[tail]=0;
    node x;
    for(int i=l;i<=n;i++)//从0开始转移向l处 
    {
        while(s.size()&&dp[tail]>=s.back().val)
        {
            s.pop_back();
        }//无用值弹出 
        x.num=tail;x.val=dp[tail];
        s.push_back(x);//加入新值 
        if(tail-s.front().num>=(r-l+1)) s.pop_front();//队列的长度 
        dp[i]=s.front().val+a[i];//此时队列最前面的是前面能到达i的最大值 
        tail++;
    }
    int ans=-maxn;
    for(int i=n-r+1;i<=n;i++)
    {
        ans=max(ans,dp[i]);
    }
    printf("%d",ans);
    return 0;
}

 

琪露诺 双端队列优化转移方程

原文:https://www.cnblogs.com/WHFF521/p/10960285.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!