zoukankan      html  css  js  c++  java
  • 琪露诺 双端队列优化转移方程

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

    题目: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;
    }
  • 相关阅读:
    Golang中使用set
    go 删除数组元素
    golang slice 简单排序
    WSGI 配置禁止反向DNS查找
    OpenStack Restful API框架介绍
    kubebuilder controller 资料学习
    package controllerutil
    JavaWeb开发好资料
    Hibernate3.6中文手册
    软件项目版本号的命名规则及格式
  • 原文地址:https://www.cnblogs.com/WHFF521/p/10960285.html
Copyright © 2011-2022 走看看