单调队列优化DP问题

news2025/3/11 12:45:39

目录

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.coloradmin.cn/o/1447697.html

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

相关文章

RBF神经网络中的RBF的英文全称是什么,是用来干什么的?

问题描述&#xff1a;RBF神经网络中的RBF的英文全称是什么&#xff0c;是用来干什么的&#xff1f; 问题解答&#xff1a; RBF神经网络中的RBF是径向基函数&#xff08;Radial Basis Function&#xff09;的缩写。径向基函数是一种在机器学习和模式识别中常用的函数类型&…

Peter算法小课堂—区间模型

Peter Pan来啦…… 最大不重叠区间数 二话不说&#xff0c;先来一道题 大家想想怎么贪心&#xff1f;我们可以将每一个美食摊位抽象成一个区间&#xff0c;区间左端点为开始排队时间&#xff0c;右端点为结束排队时间。其中&#xff0c;时间信息可以用数轴表示。 额……我们…

【Spring MVC篇】Cookie和Session的获取 Header的获取

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Spring MVC】 本专栏旨在分享学习Spring MVC的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; Cookie是客户端保存用…

【知识整理】产研中心岗位评定标准之测试岗位

为贯彻执行集团数字化转型的需要,该知识库将公示集团组织内各产研团队不同角色成员的职务“职级”岗位的评定标准; 一、定级定档目的 通过对公司现有岗位及相应岗位员工的工作能力、工作水平进行客观公正评定,确定各岗位的等级及同等级岗位员工对应的档级,从而为员工以后的晋升…

M3芯片支持追光效果吗?苹果电脑上值得玩的游戏大作有什么? Mac电脑热门游戏推荐 苹果电脑玩幻兽帕鲁 crossover软件安装

M3是苹果最新发布的芯片&#xff0c;它采用了业界领先的3纳米工艺&#xff0c;能够提供更快的速度和更高的能效。苹果电脑是一种高端的个人电脑&#xff0c;它也有着不少优秀的游戏大作&#xff0c;能够给玩家带来不同的游戏体验。那么&#xff0c;M3支持追光效果吗&#xff1f…

【AutoML】AutoKeras 进行 RNN 循环神经网络训练

由于最近这些天都在人工审查之前的哪些问答数据&#xff0c;所以迟迟都没有更新 AutoKeras 的训练结果。现在那部分数据都已经整理好了&#xff0c;20w 的数据最后能够使用的高质量数据只剩下 2k。这 2k 的数据已经经过数据校验并且对部分问题的提问方式和答案内容进行了不改变…

前端秘法引言(配置vscode, 以及html的基础)

目录 一.配置环境vscode 二.配置插件 三.vscode的实用小技巧 四.标题段落换行标签 五.格式化标签 一.配置环境vscode vscode官网https://code.visualstudio.com/ 点击右上角的download 根据不同的操作系统进行下载安装,我这里选的是Windows x64 安装好后打开,点击左上角的…

React官网摘抄

https://react.dev/learn 1、组件名称大写 2、变量&#xff0c;用{} vue中用{{}} react中用{}3、遍历 4、state使用

Python算法题集_LRU 缓存

Python算法题集_LRU 缓存 题146&#xff1a;LRU 缓存1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【队列字典】2) 改进版一【有序字典】3) 改进版二【双向链表字典】 4. 最优算法 本文为Python算法题集之一的代码示例 题146&#xff1a;LRU …

基于AI Agent探讨:安全领域下的AI应用范式

先说观点&#xff1a;关于AI应用&#xff0c;通常都会聊准召。但在安全等模糊标准的场景下&#xff0c;事实上不存在准召的定义。因此&#xff0c;AI的目标应该是尽可能的“像人”。而想要评价有多“像人”&#xff0c;就先需要将人的工作数字化。而AI Agent是能够将数字化、自…

C++ //练习 6.27 编写一个函数,它的参数是initializer_list<int>类型的对象,函数的功能是计算列表中所有元素的和。

C Primer&#xff08;第5版&#xff09; 练习 6.27 练习 6.27 编写一个函数&#xff0c;它的参数是initializer_list类型的对象&#xff0c;函数的功能是计算列表中所有元素的和。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块…

现代化端口扫描工具RustScan

今天是大年初五&#xff0c;喜迎财神 &#xff0c;祝大家✔️顺风顺水 ✔️诸事如意 ✔️财源滚滚 ✔️大吉大利 顺便提一下&#xff0c;老苏的博客启用了新域名&#xff1a; https://laosu.tech 什么是 RustScan &#xff1f; RustScan 是一款现代化的端口扫描器。能快速找到端…

学生成绩管理系统|基于Springboot的学生成绩管理系统设计与实现(源码+数据库+文档)

学生成绩管理系统目录 目录 基于Springboot的学生成绩管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员功能模块 2、学生功能模块 3、教师功能模块 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源…

选台灯的正确指标?分享考公必备的护眼台灯

台灯作为家居类不可或缺的一种照明灯具&#xff0c;在我们的日常生活中发挥着重要作用&#xff0c;不管是学生党学习阅读&#xff0c;还是办公族加班工作等等&#xff0c;都离不开它的存在。不过台灯也是有着优劣之分的&#xff0c;如果使用了一款质量不好的台灯&#xff0c;时…

CTFshow web(php命令执行59-67)

web59 <?php /* # -*- coding: utf-8 -*- # Author: Lazzaro # Date: 2020-09-05 20:49:30 # Last Modified by: h1xa # Last Modified time: 2020-09-07 22:02:47 # email: h1xactfer.com # link: https://ctfer.com */ // 你们在炫技吗&#xff1f; if(isset($_POST…

AutoGen实战应用(三):多代理协作的数据可视化

之前我完成了关于AutoGen的两篇博客&#xff0c;还没有读过这两篇博客的朋友可以先阅读以下&#xff0c;这样有助于对AutoGen的初步了解&#xff1a; AutoGen实战应用(一)&#xff1a;代码生成、执行和调试_autogen 支持的model-CSDN博客 AutoGen实战应用(二)&#xff1a;多代…

Imgui(1) | 基于imgui-SFML改进自由落体小球

Imgui(1) | 基于imgui-SFML改进自由落体小球 0. 简介 使用 SFML 做2D图形渲染的同时&#xff0c;还想添加一个按钮之类的 GUI Widget, 需要用 Dear Imgui。由于 Imgui 对于2D图形渲染并没有提供类似 SFML 的 API, 结合它们两个使用是一个比较好的方法, 找到了 imgui-SFML 这个…

nvm 安装nodejs教程【详细】

目录 一、安装nvm 二、配置镜像 三、安装nodejs 安装 查看正在用的nodejs版本 切换版本 一、安装nvm 双击安装包&#xff1a; 无脑下一步即可&#xff0c;当然你可以自定义你自己的安装目录。 安装完后&#xff0c;打开环境变量&#xff0c;你会发现nvm为我们自动配置好…

【51单片机】定时器(江科大)

7.1定时器 1.定时器介绍: 51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成 2. 定时器作用: (1)用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作 (2)替代长时间的Delay,提高CPU的运行效率和处理速度 定时器在单片机内部就像一个…

Rust入门:如何在windows + vscode中关闭程序codelldb.exe

在windows中用vscode单步调试rust程序的时候&#xff0c;发现无论是按下stop键&#xff0c;还是运行完程序&#xff0c;调试器codelldb.exe一直霸占着主程序不退出&#xff0c;如果此时对代码进行修改&#xff0c;后续就没法再编译调试了。 目前我也不知道要怎么处理这个事&am…