介绍:

  1. 单调队列优化的原理

      先回顾单调队列的概念,它有以下特征:

      (1)单调队列的实现。用双端队列实现,队头和队尾都能插入和弹出。手写双端队列很简单。

      (2)单调队列的单调性。队列内的元素具有单调性,从小到大,或者从大到小。

      (3)单调队列的维护。每个新元素都能进入队列,它从队尾进入队列时,为维护队列的单调性,应该与队尾比较,把破坏单调性的队尾弹出。例如一个从小到大的单调队列,如果要进队的新元素a比原队尾v小,那么把v弹走,然后a继续与新的队尾比较,直到a比队尾大为止,最后a进队尾。

      单调队列在DP优化中的基本应用,是对这样一类DP方程进行优化:

     $ d p [ i ] $= m i n { $ d p [ j ] + a [ i ] + b [ j ] $ } \(L ( i ) ≤ j ≤ R ( i )\) --方程(1)

      公式中的\(min\)也可以是\(max\)。方程的特点是其中关于\(i\)的项\(a[i]\)和关于\(j\)的项\(b[j]\)是独立的。\(j\)被限制在窗口\([L(i),R(i)]\)内,常见的例如给定一个窗口值\(k\),$i − k ≤ j ≤ i $。这个DP方程的编程实现,如果简单地对i做外层循环,对j做内层循环,复杂度 \(O( n^2 )\)。如果用单调队列优化,复杂度可提高到\(O(n)\)。

为什么单调队列能优化这个DP方程?

  概况地说,单调队列优化算法能把内外 $ i、j $ 两层循环,精简到一层循环。其本质原因是“外层 $ i $ 变化时,不同的 $ i $ 所对应的内层 $ j $ 的窗口有重叠”。如下图所示,$ i = i_1 $时,对应的 $ j_1 $ 的移动窗口(窗口内处理DP决策)范围是上面的阴影部分,$ i = i_2 $ 时,对应的 \(j_2\) 处理的移动窗口范围是下面的阴影;两部分有重叠。当 $ i $ 从 $ i_1 $ 增加到 $ i_2 $ 时,这些重叠的部分被重复计算,如果减少这些重复,就得到了优化。

主要方法:先写出没有单调队列的普通DP,在加上单调队列,即可

题目

代码比较明了就没加注释

)逃

P1886 滑动窗口 /【模板】单调队列

#include <bits/stdc++.h>
using namespace std;
const int N = 2000005; int n,l,r;
int a[N];
int dp[N],dq[N];
int head=1,tail=0;
int maxx=-0x3f3f3f,ans=-0x3f3f3f; int main(){
memset(dp,-0x3f3f3f,sizeof(dp));
scanf("%d%d%d",&n,&l,&r);
for (int i=0;i<=n;i++)
scanf("%d",&a[i]);
dp[0]=0;
for (int i=l;i<=n+r;i++){
while (head<=tail&&dq[head]<i-r)
head++;
while (head<=tail&&dp[dq[tail]]<=dp[i-l])
tail--;
dq[++tail]=i-l;
int temp=dp[dq[head]];
dp[i]=temp+a[i];
}
for (int i=n;i<=n+r;i++)
ans=max(ans,dp[i]);
printf("%d",ans);
return 0;
}

P2627 [USACO11OPEN]Mowing the Lawn G

【Description】

  在一年前赢得了小镇的最佳草坪比赛后,FJ变得很懒,再也没有修剪过草坪。现在,新一轮的最佳草坪比赛又开始了,FJ希望能够再次夺冠。

  然而,FJ的草坪非常脏乱,因此,FJ只能够让他的奶牛来完成这项工作。FJ有N(1 <= N <= 100,000)只排成一排的奶牛,编号为1…N。每只奶牛的效率是不同的,奶牛i的效率为E_i(0 <= E_i <= 1,000,000,000)。

靠近的奶牛们很熟悉,因此,如果FJ安排超过K只连续的奶牛,那么,这些奶牛就会罢工去开派对:)。因此,现在FJ需要你的帮助,计算FJ可以得到的最大效率,并且该方案中没有连续的超过K只奶牛。

【Input】

  * 第一行:空格隔开的两个整数N和K

  * 第二到N+1行:第i+1行有一个整数E_i

【Output】

  * 第一行:一个值,表示FJ可以得到的最大的效率值

【Sample Input】

  5 2
1
2
3
4
5

【Sample Output】

  12

【Hint】

  FJ有5只奶牛,他们的效率为1,2,3,4,5。他们希望选取效率总和最大的奶牛,但是他不能选取超过2只连续的奶牛

  FJ可以选择出了第三只以外的其他奶牛,总的效率为1+2+4+5=12。

#include <bits/stdc++.h>
#define maxn 100005 using namespace std; ll f[maxn],g[maxn],s[maxn];
int n,k,q[maxn],a[maxn];
int main()
{
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
s[i]=s[i-1]+a[i];
}
int l=1,r=1;
for (int i=1;i<=n;i++)
{
while(l<r&&i-q[l]>k)l++;
f[i]=g[q[l]]-s[q[l]]+s[i];
g[i]=max(f[i-1],g[i-1]);
while(l<=r&&g[q[r]]-s[q[r]]<=g[i]-s[i])r--;
q[++r]=i;
}
printf("%lld\n",max(f[n],g[n]));
return 0;
}

P1725 琪露诺

#include <bits/stdc++.h>
using namespace std;
const int N = 2000005; int n,l,r;
int a[N];
int dp[N],dq[N];
int head=1,tail=0;
int maxx=-0x3f3f3f,ans=-0x3f3f3f; int main(){
memset(dp,-0x3f3f3f,sizeof(dp));
scanf("%d%d%d",&n,&l,&r);
for (int i=0;i<=n;i++)
scanf("%d",&a[i]);
dp[0]=0;
for (int i=l;i<=n+r;i++){
while (head<=tail&&dq[head]<i-r)
head++;
while (head<=tail&&dp[dq[tail]]<=dp[i-l])
tail--;
dq[++tail]=i-l;
int temp=dp[dq[head]];
dp[i]=temp+a[i];
}
for (int i=n;i<=n+r;i++)
ans=max(ans,dp[i]);
printf("%d",ans);
return 0;
}

DP+单调队列详解+题目的更多相关文章

  1. (转)dp动态规划分类详解

    dp动态规划分类详解 转自:http://blog.csdn.NET/cc_again/article/details/25866971 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间 ...

  2. [poj3017] Cut the Sequence (DP + 单调队列优化 + 平衡树优化)

    DP + 单调队列优化 + 平衡树 好题 Description Given an integer sequence { an } of length N, you are to cut the se ...

  3. DP+单调队列 codevs 1748 瑰丽华尔兹(还不是很懂具体的代码实现)

    codevs 1748 瑰丽华尔兹 2005年NOI全国竞赛  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 大师 Master 题解       题目描述 Descripti ...

  4. 习题:烽火传递(DP+单调队列)

    烽火传递[题目描述]烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上.一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息:夜晚燃烧干柴,以火光传递军情.在某两座城市之间有n个烽火台,每个烽火台 ...

  5. 3622 假期(DP+单调队列优化)

    3622 假期 时间限制: 1 s 空间限制: 64000 KB 题目等级 : 黄金 Gold 题目描述 Description 经过几个月辛勤的工作,FJ决定让奶牛放假.假期可以在1-N天内任意选择 ...

  6. 数据结构图文解析之:队列详解与C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  7. (noip模拟二十一)【BZOJ2500】幸福的道路-树形DP+单调队列

    Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光. 他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图. ...

  8. 状压DP入门详解+题目推荐

    在动态规划的题型中,一般叫什么DP就是怎么DP,状压DP也不例外 所谓状态压缩,一般是通过用01串表示状态,充分利用二进制数的特性,简化计算难度.举个例子,在棋盘上摆放棋子的题目中,我们可以用1表示当 ...

  9. P3084 [USACO13OPEN]照片Photo (dp+单调队列优化)

    题目链接:传送门 题目: 题目描述 Farmer John has decided to assemble a panoramic photo of a lineup of his N cows ( ...

随机推荐

  1. cvechecker 漏洞扫描工具部署及效果展示

    cvechecker 漏洞扫描工具部署及效果展示 介绍 cvechecker的目标是通过扫描已安装的软件并将结果与CVE数据库进行匹配来报告系统上可能存在的漏洞. 官方提示: 可能会产生许多误报(漏洞 ...

  2. VMware Tanzu社区版初体验

    VMware Tanzu社区版 VMware Tanzu Community Edition 是一个功能齐全.易于管理的 Kubernetes 平台,供学习者和用户使用. 它是一个免费的.社区支持的. ...

  3. the Agiles Scrum Meeting 8

    会议时间:2020.4.16 20:00 1.每个人的工作 今天已完成的工作 个人结对项目增量开发组:完成个人项目创建的部分功能 issues:增量组:准备评测机制,增加仓库自动创建和管理 团队项目增 ...

  4. Spring Authorization Server的使用

    Spring Authorization Server的使用 一.背景 二.前置知识 三.需求 四.核心代码编写 1.引入授权服务器依赖 2.创建授权服务器用户 3.创建授权服务器和客户端 五.测试 ...

  5. PromQL的简单使用

    PromQL的简单使用 一.背景 二.PromQL的数据类型 三.字面量 1.字符串字面量 2.浮点数字面量 四.时间序列选择器 1.即时向量选择器 1.组成部分 2.指标名称和匹配器的组合 3.匹配 ...

  6. 『学了就忘』Linux基础 — 4、VMware安装

    目录 1.VMware介绍 2.VMware主要特点 3.VMware建议配置 4.VMware安装 1.VMware介绍 VMware是一个虚拟PC的软件,可以在现有的操作系统上虚拟出一个新的硬件环 ...

  7. 今天学习了BootStrap

    今天学习了BootStrap 一.BootStrap介绍 Bootstrap是一个前端开发的框架,来自 Twitter,是目前很受欢迎的前端框架.Bootstrap 是基于 HTML.CSS.Java ...

  8. 用C++实现的数独解题程序 SudokuSolver 2.6 的新功能及相关分析

    SudokuSolver 2.6 的新功能及相关分析 SudokuSolver 2.6 的命令清单如下: H:\Read\num\Release>sudoku.exe Order please: ...

  9. 有向路径检查 牛客网 程序员面试金典 C++ Python

    有向路径检查 牛客网 程序员面试金典 C++ Python 题目描述 对于一个有向图,请实现一个算法,找出两点之间是否存在一条路径. 给定图中的两个结点的指针DirectedGraphNode* a, ...

  10. 暴力尝试安卓gesture.key

    import hashlib import os import itertools f = open(r'D:\KEY\gesture.key','r') psd = f.readline() f.c ...