单调队列优化DP问题

目录

1.滑动窗口

2.最大子序和

3.旅行问题

4.烽火传递

5.绿色通道

6.修剪草坪

7.理想的正方形


1.滑动窗口

154.给定一个大小为 n≤106 的数组。

有一个大小为 k 的滑动窗口,它从数组的最左边移动到最右边。

你只能在窗口中看到 k 个数字。

每次滑动窗口向右移动一个位置。

以下是一个例子:

该数组为 [1 3 -1 -3 5 3 6 7],k 为 33。

窗口位置最小值最大值
[1 3 -1] -3 5 3 6 7-13
1 [3 -1 -3] 5 3 6 7-33
1 3 [-1 -3 5] 3 6 7-35
1 3 -1 [-3 5 3] 6 7-35
1 3 -1 -3 [5 3 6] 736
1 3 -1 -3 5 [3 6 7]37

你的任务是确定滑动窗口位于每个位置时,窗口中的最大值和最小值。

输入格式

输入包含两行。

第一行包含两个整数 n 和 k,分别代表数组长度和滑动窗口的长度。

第二行有 n 个整数,代表数组的具体数值。

同行数据之间用空格隔开。

#include<iostream>
#include<algorithm>
​
using namespace std;
​
const int N = 1000010;
​
int n, k;
int a[N], q[N];
​
int main()
{scanf("%d%d", &n, &k);for(int i = 0;i < n; i++)scanf("%d", &a[i]);int tt = -1, hh = 0;for(int i = 0;i < n; i++){if(hh <= tt && q[hh] < i - k + 1) hh++;while(hh <= tt && a[q[tt]] >= a[i]) tt--;q[++tt] = i;if(i >= k - 1) printf("%d ", a[q[hh]]);}puts("");tt = -1, hh = 0;for(int i = 0;i < n; i++){if(hh <= tt && q[hh] < i - k + 1) hh++;while(hh <= tt && a[q[tt]] <= a[i]) tt--;q[++tt] = i;if(i >= k - 1) printf("%d ", a[q[hh]]);}puts("");return 0;
}

2.最大子序和

输入一个长度为 n 的整数序列,从中找出一段长度不超过 m 的连续子序列,使得子序列中所有数的和最大。

注意: 子序列的长度至少是 1。

输入格式

第一行输入两个整数 n,m。

第二行输入 n 个数,代表长度为 n 的整数序列。

同一行数之间用空格隔开。

闫氏最优化问题分析法

在一个有限集合中求最值,或者求个数。

#include<iostream>
#include<algorithm>
#include<cstring>
​
using namespace std;
​
const int N = 300010;
​
int n, m;
int s[N], q[N];
​
int main()
{scanf("%d%d", &n, &m);for(int i = 1;i <= n; i++){scanf("%d", &s[i]);s[i] += s[i - 1];}int res = 0;for(int i = 1;i <= n; i++){res = min(res, s[i] - s[i - 1]);}int hh = 0, tt = 0;for(int i = 1;i <= n; i++){if(q[hh] < i - m) hh++;res = max(res, s[i] - s[q[hh]]);while(hh <= tt && s[q[tt]] >= s[i]) tt--;q[++tt] = i;}printf("%d\n", res);return 0;
}

3.旅行问题

1088.John 打算驾驶一辆汽车周游一个环形公路。

公路上总共有 n 个车站,每站都有若干升汽油(有的站可能油量为零),每升油可以让汽车行驶一千米。

John 必须从某个车站出发,一直按顺时针(或逆时针)方向走遍所有的车站,并回到起点。

在一开始的时候,汽车内油量为零,John 每到一个车站就把该站所有的油都带上(起点站亦是如此),行驶过程中不能出现没有油的情况。

任务:判断以每个车站为起点能否按条件成功周游一周。

输入格式 第一行是一个整数 n,表示环形公路上的车站数;

接下来 n 行,每行两个整数 pi,di,分别表示表示第 i 号车站的存油量和第 i 号车站到 顺时针方向 下一站的距离。

#include<iostream>
#include<algorithm>
#include<cstring>
​
using namespace std;
​
const int N = 1e6 + 10;
​
typedef long long LL;
​
int n;
int p[N], d[N];
LL s[N];
int q[N];
bool st[N];
​
int main()
{scanf("%d", &n);for(int i = 1;i <= n; i++)scanf("%d%d", &o[i], &d[i]);//顺时针链for(int i = 1;i <= n; i++)s[i] = s[i + 1] = o[i] - d[i];for(int i = 1;i <= n * 2; i++)s[i] += s[i - 1];int hh = 0, tt = -1;for(int i = n * 2;i >= 1; i--){if(hh <= tt && q[hh] > i + n) hh++;while(hh <= tt && s[q[tt]] >= s[i]) tt--;q[++tt] = i;if(i <= n) {if(s[q[hh]] >= s[i - 1])st[i] = true;}}//逆时针链d[0] = d[n];for(int i = 1;i <= n; i++)s[i] = s[i + 1] = o[i] - d[i - 1];for(int i = 1;i <= 2 * n; i++)s[i] += s[i - 1];hh = 0, tt = -1;for(int i = 1;i <= 2 * n; i++){if(hh <= tt && q[hh] < i - n) hh++;if(i > n){if(s[q[hh]] <= s[i])st[i - n] = true;}while(hh <= tt && s[q[tt]] <= s[i]) tt--;q[++tt] = i;}for(int i = 1;i <= n; i++)if(st[i]) puts("TAK");else puts("NIE");return 0;
}

4.烽火传递

烽火台是重要的军事防御设施,一般建在交通要道或险要处。

一旦有军情发生,则白天用浓烟,晚上有火光传递军情。

在某两个城市之间有 n 座烽火台,每个烽火台发出信号都有一定的代价。

为了使情报准确传递,在连续 m 个烽火台中至少要有一个发出信号。

现在输入 n,m 和每个烽火台的代价,请计算在两城市之间准确传递情报所需花费的总代价最少为多少。

输入格式 第一行是两个整数 n,m,具体含义见题目描述;

第二行 n 个整数表示每个烽火台的代价 ai。

在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cstring>
​
using namespace std;
​
const int N = 200010;
​
int n, m;
int w[N];
int f[N];
int q[N];
​
int main()
{scanf("%d%d", &n, &m);for(int i = 1;i <= n; i++) scanf("%d", &w[i]);int hh = 0, tt = 0;for(int i = 1;i <= n; i++){if(q[hh] < i - m) hh++;f[i] = f[q[hh]] + w[i];while(hh <= tt && f[q[tt]] >= f[i]) tt--;q[++tt] = i;}int res = 1e9;for(int i = n - m + 1;i <= n; i++)res = min(res, f[i]);return 0;
}

详细学习:模拟队列

5.绿色通道

高二数学《绿色通道》总共有 n 道题目要抄,编号 1,2,…,n,抄第 i 题要花 ai 分钟。

小 Y 决定只用不超过 t 分钟抄这个,因此必然有空着的题。

每道题要么不写,要么抄完,不能写一半。

下标连续的一些空题称为一个空题段,它的长度就是所包含的题目数。

这样应付自然会引起马老师的愤怒,最长的空题段越长,马老师越生气。

现在,小 Y 想知道他在这 t 分钟内写哪些题,才能够尽量减轻马老师的怒火。

由于小 Y 很聪明,你只要告诉他最长的空题段至少有多长就可以了,不需输出方案。

输入格式

第一行为两个整数 n,t。

第二行为 n 个整数,依次为 a1,a2,…,an。

#include<iostream>
#include<algorithm>
#include<cstring>
​
using namespace std;
​
const int N = 50010;
​
int n, m;
int q[N], f[N];
int w[N];
​
bool check(int limit)
{int hh = 0, tt = 0;for(int i = 1;i <= n; i++){if(q[hh] < i - limit - 1) hh++;f[i] = f[q[hh]] + w[i];while(hh <= tt && f[q[tt]] >= f[i]) tt--;q[++tt] = i;}for(int i = n - limit;i <= n; i++)if(f[i] <= m)return true;return false;
}​
int main()
{scanf("%d%d", &n, &m);for(int i = 1;i <= n; i++)scanf("%d", &w[i]);int l = 0, r = n;while(l < r){int mid = l + r >> 1;if(check(mid)) r = mid;else l = mid + 1;}printf("%d\n", r);return 0;
}

6.修剪草坪

1087.在一年前赢得了小镇的最佳草坪比赛后,FJ变得很懒,再也没有修剪过草坪。 现在,新一轮的最佳草坪比赛又开始了,FJ希望能够再次夺冠。 然而,FJ的草坪非常脏乱,因此,FJ只能够让他的奶牛来完成这项工作。 FJ有N只排成一排的奶牛,编号为1到N。 每只奶牛的效率是不同的,奶牛i的效率为。 编号相邻的奶牛们很熟悉,如果FJ安排超过K只编号连续的奶牛,那么这些奶牛就会罢工去开派对。 因此,现在FJ需要你的帮助,找到最合理的安排方案并计算FJ可以得到的最大效率。 注意,方案需满足不能包含超过K只编号连续的奶牛。

#include<iostream>
#include<algorithm>
#include<cstring>
​
using namespace std;
​
typedef long long LL;
​
const int N = 100010;
​
int n, m;
LL s[N];
LL f[N];
int q[N];
​
LL g(int i)
{return f[i - 1] - s[i];
}
​
int main()
{scanf("%d%d", &n, &m);for(int i = 1;i <= n; i++){scanf("%lld", &s[i]);s[i] += s[i - 1];}int hh = 0, tt = 0;for(int i = 1;i <= n; i++){if(q[hh] < i - m) hh++;f[i] = max(f[i - 1], g(q[hh]) + s[i]);while(hh <= tt && g(q[tt]) <= g[i]) tt--;q[++tt] = i;}printf("%lld\n", f[n]);return 0;
}

440.道路问题(非常复杂)

7.理想的正方形

有一个a x b的整数组成的矩阵,现请你从中找出一个n x n的正方形区域,使得该区域所有数中的最大值和最小值之差最小。

#include<iostream>
#include<algorithm>
#include<cstring>
​
using namespace std;
​
const int N = 1010;
​
int n, m, k;
int w[N][N];
int row_max[N][N], col_max[N][N];
​
void get_min(int a[], int b[], int tot)
{int hh = 0, tt = -1;for(int i = 1;i <= tot; i++){if(hh <= tt && q[hh] <= i - k) hh++;while(hh <= tt && a[q[tt]] >= a[i]) tt--;q[++tt] = i;b[i] = a[q[hh]];}
}
​
void get_max(int a[], int b[], int tot)
{int hh = 0, tt = -1;for(int i = 1;i <= tot; i++){if(hh <= tt && q[hh] <= i - k) hh++;while(hh <= tt && a[q[tt]] <= a[i]) tt--;q[++tt] = i;b[i] = a[q[hh]];}
}
​
int main()
{scanf("%d%d", &n, &m);for(int i = 1;i <= n; i++)for(int j = 1;j <= m; j++)scanf("%d", &w[i][j]);for(int i = 1;i <= n; i++){get_min(w[i], row_min[i], m);get_max(w[i], row_max[i], m);}int res = 1e9;int a[N], b[N], c[N];for(int i = k;i <= m; i++){for(int j = 1;j <= n; j++) a[j] = row_min[j][i];get_min(a, b, n);for(int j = 1;j <= n; j++) a[j] = row_max[j][i];get_max(a, c, n);for(int j = k;j <= n; j++) res -= min(res, c[j] - b[j]);}printf("%d\n", res);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/680772.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

游泳时可以听歌的耳机有哪些?戴游泳耳机有哪些好处?

游泳和跑步在某种程度上相似&#xff0c;特别是在短距离冲刺时&#xff0c;大脑似乎变得空白&#xff0c;而在中长距离的有氧运动中&#xff0c;身体感到疲劳&#xff0c;但大脑却异常清晰&#xff0c;时间却显得格外漫长。如何打发时间&#xff0c;让游泳锻炼变得不无聊&#…

力扣面试题 16.21. 交换和(哈希表)

Problem: 面试题 16.21. 交换和 文章目录 题目描述思路及解法复杂度Code 题目描述 思路及解法 1.分别求取array1与array2数组每一个元素的和&#xff08;sum1与sum2&#xff09;并同时将array2的元素存入一个set集合中&#xff1b; 2.如果sum1和sum2的和为奇数&#xff0c;则不…

使用 Windows 11/10 上的最佳 PDF 转 Word 转换器释放 PDF 的潜力

毫无疑问&#xff0c;PDF 是最好的文档格式之一&#xff0c;但就像其他格式一样&#xff0c;有时它们确实会带来一些限制。例如&#xff0c;在某些情况下&#xff0c;您可能想要将 PDF 转换为 Word。在这种情况下&#xff0c;您始终可以借助 PDF 到 Word 转换器的帮助。 为了说…

Java实现软件学院思政案例库系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统管理员2.2 普通教师 三、系统展示四、核心代码4.1 查询思政案例4.2 审核思政案例4.3 查询思政课程4.4 思政案例点赞4.5 新增思政案例评语 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的软件学…

谁再用Arrays.asList就开除谁

谁再用Arrays.asList就开除谁 hi&#xff0c;我是achang&#xff0c;今天说一个使用Arrays.asList后对应出现的一系列坑&#xff0c;因为他有那么多坑&#xff0c;所以会有开玩笑的说&#xff1a;谁再用Arrays.asList就开除谁 那Arrays.asList的作用很简单&#xff0c;就是把…

86.分布式锁理论分析

文章目录 前言一、为什么需要分布式锁&#xff1f;二、基于 Redis 分布式锁怎么实现&#xff1f;三、Redis 分布锁存在的问题3.1 死锁问题3.2 锁过期时间问题3.3 锁被别人释放问题 四、Redis 分布锁小结五、Redis 主从同步对分布式锁的影响六、Redlock 方案七、Redlock 的争论7…

autojs通过正则表达式获取带有数字的text内容

var ctextMatches(/\d/).findOne()console.log("当前金币"c.text()) // 获取当前金币UiSelector.textMatches(reg) reg {string} | {Regex} 要满足的正则表达式。 为当前选择器附加控件"text需要满足正则表达式reg"的条件。 有关正则表达式&#xff0c;可…

揭秘外观模式:简化复杂系统的关键设计策略

前言 外观模式&#xff08;Facade Pattern&#xff09;是一种结构型设计模式&#xff0c;它隐藏了系统的复杂性&#xff0c;并向客户端提供了一个可以访问系统的接口。这种类型的设计模式向现有的系统添加一个接口&#xff0c;来隐藏系统的复杂性。这种模式涉及到一个单一的类…

【C语言】实现单链表

目录 &#xff08;一&#xff09;头文件 &#xff08;二&#xff09;功能实现 &#xff08;1&#xff09;打印单链表 &#xff08;2&#xff09;头插与头删 &#xff08;3&#xff09;尾插与尾删 &#xff08;4&#xff09; 删除指定位置节点 和 删除指定位置之后的节点 …

蓝桥杯嵌入式第9届真题(完成) STM32G431

蓝桥杯嵌入式第9届真题(完成) STM32G431 题目 分析和代码 main.h /* USER CODE BEGIN Header */ /********************************************************************************* file : main.h* brief : Header for main.c file.* …

Java-并发高频面试题-2

接着之前的Java-并发高频面试题 7. synchronized的实现原理是怎么样的&#xff1f; 首先我们要知道synchronized它是解决线程安全问题的一种方式&#xff0c;而具体是怎么解决的呢&#xff1f;主要是通过加锁的方式来解决 在底层实现上来看 是通过 monitorenter、monitorexit…

【Spring原理进阶】SpringMVC调用链+JSP模板应用讲解

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Spring 狂野之旅&#xff1a;底层原理高级进阶》 &#x1f680…

【Python网络编程之Ping命令的实现】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;Python开发技术 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; Python网络编程之Ping命令的实现 代码见资源&#xff0c;效果图如下一、实验要求二、协议原理2…

所谓的意志力,也许根本就不存在

许多讲自我提升的书&#xff0c;往往会把成功的原因归结为两点&#xff1a;自律&#xff0c;以及专注。 他们会告诉你&#xff1a;为什么别人能够成功、而你不能&#xff1f;第一是你不够自律&#xff0c;无法每天雷打不动地坚持「好习惯」&#xff1b;第二&#xff0c;是你不够…

[Java][算法 滑动窗口]Day 02---LeetCode 热题 100---08~09

第一题 无重复字符串的最长子串 思路 其实就是在字符串S中 找到没有重复的最长子串的长度 这道题的难点就是在于如何判断最长并且无重复 首先 最长长度 可以使用变量max记录保存 再者 判断有无重复 最简单的方法就是 暴力遍历法 即对于每次找的子串都再次寻找遍历…

【Chrono Engine学习总结】5-sensor-5.1-sensor基础并创建一个lidar

由于Chrono的官方教程在一些细节方面解释的并不清楚&#xff0c;自己做了一些尝试&#xff0c;做学习总结。 1、Sensor模块 Sensor模块是附加模块&#xff0c;需要单独安装。参考&#xff1a;【Chrono Engine学习总结】1-安装配置与程序运行 Sensor Module Tutorial Sensor …

【国产MCU】-CH32V307-基本定时器(BCTM)

基本定时器(BCTM) 文章目录 基本定时器(BCTM)1、基本定时器(BCTM)介绍2、基本定时器驱动API介绍3、基本定时器使用实例CH32V307的基本定时器模块包含一个16 位可自动重装的定时器(TIM6和TIM7),用于计数和在更新新事件产生中断或DMA 请求。 本文将详细介绍如何使用CH32…

苹果Mac键盘如何将 F1 到 F12 取消按Fn

苹果电脑安装了Win10操作系统之后&#xff0c;F1到F12用不了怎么办的解决方法。本文将介绍一些解决方法&#xff0c;帮助您解决无法使用F1到F12功能键的问题。 使用 Mac系统的人都知道&#xff0c;Mac系统默认是没有开启 F1-F12 的使用的&#xff0c;平时我们使用的系统都可以使…

AcWing 802. 区间和 离散化

文章目录 题目链接题目描述解题思路代码实现总结 题目链接 链接: AcWing 802. 区间和 题目描述 解题思路 离散化是一种常用的技巧&#xff0c;它能够将原始的连续数值转换为一组离散的值&#xff0c;从而简化问题的处理。在这段代码中&#xff0c;离散化的过程主要分为三个步…

那些也许你不知道的操作符!

前言 操作符有很多种&#xff0c;目前我们已经了解了一部分 例如最简单的、-、*、/、&#xff0c;还有我们学到的&&&#xff0c;||&#xff0c;!等&#xff0c;但是操作符可不是就只有这么些的&#xff0c;让我们一起来看看吧 目录 1. 移位操作符 原码、反码、补码…