E-魔法猫咪(遇到过的题,做个笔记)

题解:

来自学长们思路:

其中一种正解是写单调队列。限制队列内的数单调递增,方法为每当新来的数据比当前队尾数据小时队 尾出列,直到能够插入当前值,这保证了队头永远是最小值。因此总体思路是队尾不断插入新值的同时 不断输出当前队头元素。在输出队头元素时有两点要注意:

1. 队尾前进 m次后再开始输出。

2. 确认当前队头值的下标仍在区间范围内,反之则需要队头出队直到进入当前区间。

#include <iostream>
#include <vector>
using namespace std;
int main()
{int n, m;cin >> n >> m;vector<int>arr(n + 1);			//用于存放数据vector<int>q(n + 1);		//存最小数的下标int head = 1, tail = 0;			//模拟双向队列,把头定为 q[1],尾先定为q[0],且该队列是单调递增的for (int i = 1; i <= n; i++){cin >> arr[i];while (1)	//通过移动末尾的位置来弹出队尾元素,直到队尾能插入新的更小的数据{if (arr[i] < arr[q[tail]] && head <= tail)	tail--;	//尾移动弹出元素过程中,要保证更小的元素能作为队头所以才是(&&head<=tail)else{q[++tail] = i;		//将元素插入队尾break;		//更小数据插入后就结束循环}}if (i - q[head] + 1 > m)	head++;		//发现该元素与队头元素的距离超过了m,就让队头的位置往后移动,因为原先队头元素已经不是该元素所在区间范围中了if (i >= m)	cout << arr[q[head]] << endl;  //当判断过m个元素后才开始输出队头元素}return 0;}

 就以样例为例,说下过程:

一开始第一个数是16,发现16>0(因为arr[q[tail]]=arr[q[0]]=arr[0]=0),然后16的下标1经由q[++tail]存到了q[1]的位置,也是head所指的位置。然后遇到5,发现5<16,就tail--(tail从1变成了0),然后下一次循环,就由q[++tail],tail变成1, 5的下标2覆盖了16的下标1。

然后6,9都>5,分别让下标存到了q[2]=3,q[3]=4;在遇到9的时候,从16到9刚好满足m的长度,输出arr[q[head]],而head这里存放的正是由16~9这4个数中最小的数--5的下标2

然后遇到了5,发现5<9,tail--,tail变为了2,然后5<6,tail--,tail变为了1;然后下一次循环到else语句中,经由q[++tail],tail变为2, 5的下标存到了q[2]=5。而5~5这4个数中最小的元素仍是第一个5(下标为2的那个5),把这个5输出。

然后是13,这时,13的下标存到了q[3]=6,但是13的下标6-q[head]+1(6-2+1)=5>m,发现第一个5~13是的长度是5,而第一5并不在13所在的区间范围中,这时head++,往后移一位,head变为2,输出符合13所在区间的最小的数,即下标为5的那个5

同理然后就是q[4]=7,q[5]=8,直到遇到8(下标为9),发现经过tail的移动以及覆盖,q[2]=5,q[3]=9,但这时候9-q[head]+1(9-5+1)=5>m,这时第二个5并不是8所在范围中,这时head++,head=3;输出符合8所在区间的最小的数,即8

同理直到for遍历n次后

输出:

5 5 5 5 5 8 8

总之,队列q中存放的是,每个长度为m的组中最小值的下标

当然,head=1,tail=0,就是为了方便通过移动tail位置(用++tail)弹出队尾元素以及弹出队头元素(当第一个数据的下标输入进去后,tail通过自增,tail=1=head),就拿16和后面的5来说,16输入进去后,tail=head=1;但是5<16,这是tail--,变为0但是head仍然为1,后续经过++tail,让tail重新变为1,5的下标覆盖16的下标。

然后是&& head <= tail条件,这是为了防止已经把队列有效元素都弹完了,还继续弹。比如head=3时,如果没有该条件限制,当遇到一个整个数据中最新的数,比如1时,会不断弹,哪怕tail=2了,还在移动tail位置,此时等到再插入该数下标时,会把下标放在无效位置,因为head=3,q[3]以后才是有效位置

参考(来自学长们题解):

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

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

相关文章

openlayers 入门教程(九):overlay 篇

还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#xff0c;webgl&#xff0c;ech…

Spring框架提供三个核心服务

1. IOC&#xff1a;控制反转服务 由“Spring容器对象”完成指定类的实例对象的创建 2. DI&#xff1a;依赖注入 由“Spring容器对象”完成指定对象的初始化的服务 3. AOP:面向切面编程 降低开发人员使用代理设计模式难度&#xff0c;开发人员只需要专注于切面类的开发即可…

vue-cli打包 nodejs内存溢出 vue2.x Last few GCs

遇到这种情况百度各种博客&#xff0c;什么改package.json里的配置&#xff0c;什么安装increase-memory-limit &#xff0c;都尝试了并没什么用处&#xff0c;最后解决方案为执行下方名单&#xff0c;再次打包就成功了&#xff1a; export NODE_OPTIONS--max_old_space_size4…

android 内存优化

什么是内存泄漏? 如果一个无用对象&#xff08;不需要再使用的对象&#xff09;仍然被其他对象持有引用&#xff0c;造成该对象无法被系统回收&#xff0c;以致该对象在堆中所占用的内存单元无法被释放而造成内存空间浪费&#xff0c;这中情况就是内存泄漏。 在Android开发中…

单元测试 mockito(二)

1.返回指定值 2.void返回值指定插桩 3.插桩的两种方式 when(obj.someMethod()).thenXxx():其中obj可以是mock对象 doXxx().wien(obj).someMethod():其中obj可以是mock/spy对象 spy对象在没有插桩时是调用真实方法的,写在when中会导致先执行一次原方法,达不到mock的目的&#x…

好物视频素材在哪找?视频素材大全app下载

创作优质视频内容不仅仅是一种艺术&#xff0c;也是一种科学&#xff0c;需要对素材的深刻理解和精心挑选。掌握了这些高清无水印视频素材&#xff0c;您就拥有了创作引人入胜视频内容的强大工具。以下是更多精选的视频素材网站&#xff0c;旨在为您的视频项目提供更广阔的视野…

Python | Leetcode Python题解之第10题正则表达式匹配

题目&#xff1a; 题解&#xff1a; class Solution:def isMatch(self, s: str, p: str) -> bool:m, n len(s), len(p)dp [False] * (n1)# 初始化dp[0] Truefor j in range(1, n1):if p[j-1] *:dp[j] dp[j-2]# 状态更新for i in range(1, m1):dp2 [False] * (n1) …

专升本--python运算符总结

运算优先级 同一个等级是没有先后顺序的&#xff0c;此外&#xff0c;赋值语言的先后问题&#xff1a; 赋值的顺序从上往下&#xff0c;同一行一般都是代表同时进行赋值&#xff0c;如图所示&#xff1a; 一.and A and B&#xff0c;若A,B有任意一个为假&#xff08;0&#x…

希尔排序和快排里的小区间优化

希尔排序 希尔排序是插入排序的优化。 当一串数是逆序时&#xff0c;那么每插入一个数&#xff0c;前面的数都会向后面挪动。 那么这是插入排序的时间复杂度&#xff0c;就会达到O(n^2) 希尔排序是对数组里的数进行预排序。 防止插入排序出现最坏的情况。 预排序&#xf…

代码随想录-图论

797.所有可能的路径&#xff1a; . - 力扣&#xff08;LeetCode&#xff09; class Solution {List<List<Integer>> ansnew LinkedList<>();List<Integer> listnew LinkedList<>();public List<List<Integer>> allPathsSourceTarg…

ABC318 F - Octopus

解题思路 对于每个宝藏维护个区间&#xff0c;答案一定在这些区间中对于每个区间的端点由小到大排序对于每个点进行判断&#xff0c;若当前位置合法&#xff0c;则该点一定为一个右端点则该点到前一个端点之间均为合法点若前一个点不合法&#xff0c;则一定是某一个区间限制的…

Vue3:使用Pinia存储、读取、修改数据

一、存储数据 Pinia插件中&#xff0c;存储数据的配置项是state count.ts import {defineStore} from piniaexport const useCountStore defineStore(count,{// 真正存储数据的地方state(){return {sum:6}} })loveTalk.ts import {defineStore} from piniaexport const use…

Xen Server 8 Install

Xen Sevrer 前言 XenServer&#xff08;以前称为 Citrix Hypervisor&#xff09;是业界领先的平台&#xff0c;实现了经济高效的桌面、服务器和云虚拟化基础结构。XenServer 支持任意规模或类型的组织整合计算资源&#xff0c;以及将计算资源转换为虚拟工作负载&#xff0c;从…

RESTful API说明

RESTful API&#xff08;Representational State Transfer&#xff09;是一种用于设计网络应用程序的架构风格。它基于 HTTP 协议&#xff0c;通过使用统一的资源标识符&#xff08;URL&#xff09;来访问和操作资源。 RESTful API 的设计原则包括&#xff1a; 资源标识符&am…

SpringBoot2升级到SpringBoot3总结

最近公司在做监控日志平台的迁移&#xff0c;从NewRelic迁移到Dynatrace&#xff0c;为了配合迁移&#xff0c;有一个前提就是把SpringBoot2升级到SpringBoot3。 我们这边的项目大多数都是KotlinSpringBoot2.X的技术栈&#xff0c;现在要全部升级到最新的SpringBoot3.2.2或者S…

c++协程详解(二)

前言 这是c协程实现第二篇&#xff0c;这里开始我们将开始真正意义上开始实现协程。对协程基础流程不清楚的&#xff0c;可以看我的第一篇。 后续可能需要一定的模板知识&#xff0c;可以看下我的模板的文章&#xff0c;那些知识就完全够用了。本篇将实现一个协程封装的异步任…

Redis慢日志

SLOWLOG 是用来读取和重置 Redis 慢查询日志的命令&#xff0c;Redis 2.2.12 版本开始支持 1.Redis 慢查询日志概述 客户端从发送命令到获取返回结果经过了以下几个步骤&#xff1a; 1. 客户端发送命令 2. 该命令进入 Redis 队列排队等待执行 3. Redis 开始执行命令 - Red…

浅析JavaWeb内存马基础原理与查杀思路

文章目录 前言Java内存马内存马分类&原理JavaWeb三大组件注入Servlet内存马注入Filter型内存马JAVA Agent内存马 哥斯拉木马0x01 WebShell0x02 MemShell0x03 FilterShell0x04 Arthas排查0x05 scanner查杀 总结 前言 几年前写过《Web安全-一句话木马》&#xff0c;主要介绍…

PurpleKeep:提供Azure管道以创建基础设施并执行Atomic测试

关于PurpleKeep PurpleKeep是一款功能强大的安全测试自动化工具&#xff0c;该工具能够通过提供Azure管道以创建基础设施&#xff0c;并帮助广大研究人员执行Atomic测试。 随着攻击技术种类的迅速增加&#xff0c;以及EDR&#xff08;端点检测和响应&#xff09;和自定义检测规…

二叉树层序遍历 及相关题目

1&#xff0c;力扣102 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]]示例…