单调队列优化DP

【C++】单调队列 详解 今天我们来讲一下单调队列与栈。 这两种数据结构虽然没有在c++的stl中有直接的实现,但是在做题过程中,很容易有单调队列(栈)的使用,尤其是在一些比较难的题目中。 目录单调队列1.1 单调队列介绍1.2 单调队列的应用1.2.1 滑动窗口最大值1.2.1.1 题目描述1.2.1.2 结题思路方法一(优先队列)方法二 (单调队列)1.3 单调队列的模拟实现1.4 其他例题 单调队列 1.1 单调队列介绍 单调队列 是 队列中元素之间的关系具有单调性,而且,队首和队尾都可以进行出队操作,只有队尾可以进行入队 阅读详情

一、单调队列

单调队列,即单调递减或单调递增的队列。使用频率不高,但在有些程序中会有非同寻常的作用。——百度百科

重点在哪里?

使用频率不高 单调递减或单调递增的队列。

单调队列是一个双端队列,一般来说队尾用于维护单调性,队头用于保持队列大小。
单调队列有两个性质:

  1. 队列中的元素在原来列表中的顺序是单调递增的。
  2. 队列中的元素大小是单调递增或递减。

二、实现

我们将单调队列看做是一个大小一定的窗口,在列表中滑动,维护以上两个性质。
我们将单调队列的维护分为两步:

  1. 维护队尾。比较列表当中的当前元素与队尾元素,若当前元素更优,则弹出队尾,直到插入当前元素可以满足单调性时,将当前元素插入队尾。

  2. 维护队头。将数组下标在窗口之外的弹出。

例题:洛谷 P1886 滑动窗口 /【模板】单调队列

#include<iostream>
#include<cstdio>
#define MAXN 1000010
using namespace std;
int n,k;
int a[MAXN];
int q[MAXN],p[MAXN],head,tail;
void get_min()
{
	head=1;
	tail=0;
	for(int i=1;i<=n;i++)
	{
		while(tail>=head&&q[tail]>a[i])
			tail--;
		q[++tail]=a[i];
		p[tail]=i;
		while(p[head]<=i-k)
			head++;
		if(i>=k)
			printf("%d ",q[head]);
	}
	printf("\n");
}
void get_max()
{
	head=1;
	tail=0;
	for(int i=1;i<=n;i++)
	{
		while(tail>=head&&q[tail]<a[i])
			tail--;
		q[++tail]=a[i];
		p[tail]=i;
		while(p[head]<=i-k)
			head++;
		if(i>=k)
			printf("%d ",q[head]);
	}
	printf("\n");
}
int main()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	get_min();
	get_max();
	return 0;
 } 

三、应用:优化DP

因为单调队列的单调性,所以我们可以用它来进行降低DP维数,进行时间和空间的优化。
例题:粉刷木板

题目描述
有 N N N 块木板从左到右排成一行,有 M M M 个工匠对这些木板进行粉刷,每块木板至多被粉刷一次。
第 i i i 个木匠要么不粉刷,要么粉刷包含木板 S i S_i Si​ 且长度不超过 L i L_i Li​ 的连续的一段木板,每粉刷一块可以得到 P i P_i Pi​ 的报酬。不同工匠的 $ i _i i​不同。 请问如何安排能使工匠们获得的总报酬最多。

输入格式
第一行包含两个整数 N N N 和 M M M 。
接下来 M M M 行,每行包含三个整数 L i , P i , S i L_i,P_i,S_i Li​,Pi​,Si​。

输出格式
输出一个整数,表示结果。

样例输入
8 4
3 2 2
3 2 3
3 3 5
1 1 7
样例输出
17

数据范围与提示
对于 100 % 100\% 100%的数据, 1 ≤ N ≤ 16000 1≤N≤16000 1≤N≤16000, 1 ≤ M ≤ 100 1≤M≤100 1≤M≤100, 1 ≤ P i ≤ 10000 1≤P_i≤10000 1≤Pi​≤10000。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m;
struct node
{
	int l,p,s;
}
a[110];
bool cmp(node a,node b)
{
	return a.s<b.s;
}
int q[20000],head,tail;
int f[110][20000];
void dp()
{
	for(int i=1;i<=m;i++)
	{
		head=1,tail=0;
		for(int k=max(a[i].s-a[i].l,0);k<=a[i].s-1;k++)
		{
			while(head<=tail&&f[i-1][q[tail]]-q[tail]*a[i].p<=f[i-1][k]-k*a[i].p)
				tail--;
			q[++tail]=k;
		}
		for(int j=1;j<=n;j++)
		{
			f[i][j]=max(f[i-1][j],f[i][j-1]);
			if(j>=a[i].s)
			{
				while(head<=tail&&j-q[head]>a[i].l)
					head++;
				if(head<=tail)
					f[i][j]=max(f[i][j],f[i-1][q[head]]+(j-q[head])*a[i].p);
			}
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
		scanf("%d%d%d",&a[i].l,&a[i].p,&a[i].s);
	sort(a+1,a+m+1,cmp);
	dp();
	printf("%d",f[m][n]);
	return 0;
}
单调队列 & 单调队列优化DP & 题目推荐 来看一道题 扫描 题目描述 有一个 1 ∗ n 的矩阵,有 n 个正整数。 现在给你一个可以盖住连续的 k 的数的木板。 一开始木板盖住了矩阵的第 1 ∼ k 个数,每次将木板向右移动一个单位,直到右端与第 n 个数重合。 每次移动前输出被覆盖住的最大的数是多少。 输入格式 第一行两个数,n,k,表示共有 n 个数,木板可以盖住 k 个数。 第二行 n 个数,表示矩阵中的元素。 输出格式 共 n ... 阅读详情

相关推荐

从零到一:RT-Thread与W5500的硬件抽象层设计哲学与实践启示

本文深入探讨了RT-Thread操作系统下W5500以太网模块的硬件抽象层(HAL)设计哲学与实践。通过GD32F103和STM32F103平台的适配案例,详细阐述了如何利用RT-Thread的驱动框架实现跨平台硬件无关性、模块化设计及配置定制,为嵌入式开发者提供了可复用的HAL设计方法论和实战经验。

7z8x2c4v6b9的博客 197

Leetcode单调队列、优先队列(堆)、单调栈、归并排序刷题总结

数据结构补充

studyForMokey的博客 1133

普冉PY32F002B ADC内部参考电压VREFINT的误差补偿与低功耗优化实践

本文详细介绍了普冉PY32F002B单片机在锂电池供电场景下ADC内部参考电压VREFINT的误差补偿与低功耗优化实践。通过分析GPIO配置、分压电阻匹配、采样时间设置等硬件设计要点,结合实时测量VREFINT电压值和软件补偿算法,有效提升了ADC测量精度至5mV以内,并实现了分压电路功耗控制与采样频率优化,为低成本消费电子项目提供了完整的解决方案。

846

单调队列【总结】

一、基本概念 单调队列是指:单调递增或单调递减的队列。所以它也有如下几个性质: 1.队列中的元素在原来的列表中的位置是由前往后的(随着循环顺序入队)。 2.队列中元素的大小是单调递增或递减的。 3.从队尾入列,队首或队尾出列 时间复杂度:O(N) 二、例题 1.最大子序和(dp+单调队列优化) 题目描述 输入一个长度为n的整数序列,从中找出一段不超过m的连续子序列,使得整个序列的和最大。 例如 1,-3,5,1,-2,3 当m=4时,S=5+1-2+3=7 当m=2或m=3时,S=5+1=6 输入 第一行两

算法小猪的博客 2147

基于物联网技术智慧园林绿化养护管理信息平台

近几年来,随着经济不断的发展,城市面积不断的扩大,城市管理中的园林绿化工作也在这种趋势下不断的发生着深刻改变。管养企业是否按制定的管养计划严格执行?绿化事件整改是否及时到位?绿地面积是否在稳步增长?管养的效果如何?如何客观评价管养企业的管养工作?这些都是我们各级管理者需要面对的问题。   智慧园林绿化养护管理信息平台的开发思路以“考核”为核心,整个信息平台体现出“新、快、高、全、享”五个特点。   智慧园林绿化养护管理信息平台的整个开发理念为:依托五大技术手段(全球卫星定位系统技术、地理信...

Cesium的博客QQ2252224326 2459

如何入门强化学习

很多同学在入门强化学习的时候都会遇到困难,那我这里就简单介绍一下应该如何入门强化学习,并以开源代码为例详解强化学习实战。

seeksister的博客 3302

[数据结构]--单调队列

类比单调栈队首到队尾单调递增/递减。

weixin_74375289的博客 3286

深入理解HanLP1.x,填平可能遇到的坑

提取指定数量的摘要。自定义词典为什么要单独领出来讲呢?因为在我们的业务开发中,可能分词的效果并不理想,需要定制自己的词库,索引更加常用。例如:小米su7特斯拉modelY比亚042025款6575767670908我们需要分出小米su72025款等词。我们分别看看用字典和不用字典的效果。

static_coder的博客 977

基础算法知识点------单调队列

单调队列

weixin_43743711的博客 1806

AI工作流革命:从n8n到Sora2,揭秘自动化视频创作的底层逻辑

本文深入探讨了AI工作流在自动化视频创作中的应用,重点介绍了n8n、Coze和Sora2的组合如何实现从链接输入到视频输出的全流程自动化。通过三层架构解析、关键技术模块优化及成本控制策略,这套方案显著提升了视频生产效率,适用于电商、热点追踪等多种场景。

gg901的博客 1082

喷涂机器人系列编程:ABB IRB 5500_(7).喷涂质量控制与优化

通过编程手段对ABB IRB 5500喷涂机器人进行质量控制和优化,可以显著提高喷涂的均匀性和附着力,减少涂层缺陷。具体的方法包括喷涂参数的调整、路径规划的优化、喷涂效果的检测与反馈,以及喷涂参数的动态调整。综合评估系统可以进一步确保喷涂质量的稳定性和一致性,帮助汽车制造企业提高产品质量和生产效率。

zhubeibei168的博客 851

论单调队列优化DP

单调队列优化DP(区间、背包、树形和数位)

2401_90042730的博客 2051

【数字IC刷题】华为海思数字IC笔试题(1)详细解析版

【数字IC刷题】华为海思数字IC笔试题(1)详细解析版

MoorePlus的博客 4218

DP单调队列优化

内,那么,通过下图可以发现,其实整个DP的过程类似单调队列滑动窗口。,所以前区间的最小值一定能维护到,方案可行。所以,我们可以考虑用单调队列来优化枚举。由于一段的连续长度不能超过。这个点已经加入单调队列了,不必再加)。是定值,不用枚举,而对于剩下的。可以考虑用单调队列维护最大值。那么,对于当前点的最大值就是。加入单调队列中,维护最大值(的循环,优化后时间复杂度为。,所以答案通过队头就可以。,单调队列循环次数一共是。,先按照题目计算出价值。,然后放入单调队列中。由于普通思想需要枚举。

STY_fish_2012的博客 814

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

单调队列优化dp小结

拿手拆一拆易得:f[i][j]=c[i]*j+min(f[i-1][k]+(x[i]-x[i-1])*k*k-c[i]*k)(max(0,j-c[i])<=k<=j)这题和单调队列毫无关系,设f[i][j]表示后两步为i,j的最大值,转移枚举j,再枚举k,用minn=max(f[i][j])转移一下即可,可以用上一个k的延续过来。拿脚推易得:f[i][j]=min(f[i-1][k]+(x[i]-x[i-1])*k*k+c[i]*(j-k))(max(0,j-c[i])<=k<=j)

2301_81913843的博客 1154

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

dp单调队列优化

本文介绍了单调栈和队列的基本概念及其实现方法,并通过洛谷P2034题目展示了单调队列在动态规划中的应用。单调栈通过手动实现或STL库保持元素单调性,而队列则遵循先进先出原则。在解决P2034问题时,通过将问题转化为删除最小和的方式,利用单调队列优化比大小过程,显著提升了效率。文章提供了手搓和STL两种实现代码,帮助读者理解并应用该算法。

xiaowu114514的博客 1214

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

DP 优化一:单调队列优化 DP

本文介绍了动态规划中的单调队列优化方法。首先解释了单调队列的概念及其在线性时间内求区间最值的优势,通过滑动窗口例题展示了具体实现过程。然后重点讲解了如何利用单调队列优化特定形式的DP转移方程,即形如f[i]=min{f[j]+F(j)+C}的情况。最后以一道粉刷围栏的题目为例,展示了如何将暴力DP解法转化为单调队列优化形式,通过数学变形将转移方程改写为可优化结构,从而显著提升算法效率。文章通过具体例题和代码示例,系统性地阐述了单调队列优化的原理和应用场景。

cwplh的博客 657

单调队列优化DP——习题收集

前言 感觉可以用单调队列优化dp的模型还是挺活的,开个随笔记录一些遇到的比较有代表性的模型,断续更新。主要做一个收集整理总结工作。 记录 0x01 POJ - 1821 Fence,比较适合入门的题,写出转移方程后可以比较容易的看出决策变量的取值范围的界是单调变化的,以及价值拆开之后也是单调的 #include<iostream> #include<cstdio> #in...

weixin_30508309的博客 228

HDU 5945 单调队列优化DP

比赛时一直以为是个数学题,一直没有想到用优先队列优化DP 看来需要好好学一学

qq_29904713的博客 260

单调队列优化DP动态规划(1)

目录 一.前言 二.例题1:单调队列本身的灵活应用——测量温度 1.题目 题目描述 输入 输出 输入样例 输出样例 2.思路 三.例题2:单调队列优化DP:猴子 1.题目 题目描述 输入 输出 输入样例   输出样例 2.思路  四.总结 一.前言 学好了单调队列不仅可以单独使用,他还可以有更多的广泛用途。这里我主要讲其对动态规划的优化,较简单。 二.例题...

weixin_43908980的博客 797

单调队列优化dp

如上图,可以跳到 3−7 这个区间,跳到 3 和 4 的时候,都是消耗劳累度的,但是我们选择哪个更好呢,当然是越大的越好,因为高度越高,下一次越有利,如上图,当我们跳到 4 ,下一次跳到 3 的时候就不增加劳累度。如果暴力枚举那个区间,一般会超时,于是我们可以选择将最大值放入队头的最大值或者最小值,通过这样维护我们可以减去暴力枚举的过程,优化了时间复杂度。维护这样一个队列的好处是,当我们想求最大值的时候,我们只需要保证队列是单调递增的,于是每次取出队头就是我们的最大值。第一个元素下标进队列,此时队列为。

m0_74176921的博客 639

单调队列优化dp学习笔记

这类问题一般是朴素的复杂度大的转移很好写。 然后转移类似rmq的问题。 需要注意的是:在新值与队头元素判断谁更优的时候,需要把两者放在一个参考系下进行比较。 就是 把旧值等效放在新值的位置上的值才是旧值的真实值。 cf372C 题意:给你m个烟花,每个烟花在t_i时刻在x位置被点燃,得到b_i+|a_i-x|的分,初始选择任意位置,每分钟移动一个单位。问最大得分是多少。 根据题目可以写出一个暴力的dp for(int i=2;i<=m;i++){ for(int j=1;j<=n;j++){

pubgoso的博客 323
上一篇: 数位DP详解
下一篇: 树状数组详解(区间修改和单点查询)
Wu_while
博客等级 码龄6年 50粉丝 53原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值