2022GDUT寒训专题一I题
题目
题面
给一个长度为 N的数组,一个长为 K的滑动窗体从最左端移至最右端,你只能看到窗口中的 K 个数,每次窗体向右移动一位,如下图:
| 窗口位置 | 最小值 | 最大值 |
|---|---|---|
| [1 3 -1] -3 5 3 6 7 | -1 | 3 |
| 1 [3 -1 -3] 5 3 6 7 | -3 | 3 |
| 1 3 [-1 -3 5] 3 6 7 | -3 | 5 |
| 1 3 -1 [-3 5 3] 6 7 | -3 | 5 |
| 1 3 -1 -3 [5 3 6] 7 | 3 | 6 |
| 1 3 -1 -3 5 [3 6 7] | 3 | 7 |
你的任务是找出窗体在各个位置时的最大值和最小值。
输入格式
第 1 行:两个整数 N 和 K; 第 2 行:N个整数,表示数组的 N个元素(≤2e9);
输出格式
第一行为滑动窗口从左向右移动到每个位置时的最小值,每个数之间用一个空格分开; 第二行为滑动窗口从左向右移动到每个位置时的最大值,每个数之间用一个空格分开。
样例
Input&Output
8 3
1 3 -1 -3 5 3 6 7
-1 -3 -3 -3 3 3
3 3 5 5 6 7
思路
这题是滑动窗口找最值问题,我们需要用到的工具是双头的单调队列。
若找的是最大值,则要构造一个递减的队列,反之递增。
解释如下:
1、首先明确我们遍历数组时,当前下标的意思为滑动窗口的右端点为该元素。记滑动窗口大小为k。
2、假设存在滑动窗口右端点a,记滑动窗口下一个元素为b,对于ab二者我们有两种情况:b>=a或者b<a(分别对应第3和4点)。
3、b>=a:我们知道b在a的右边,那么b影响的范围是[b,b+k-1],a影响的范围是[a,a+k-1]。因为b-a=1,所以b影响的范围始终比a影响的范围大。这意味着,一旦我们能走到b点,a就不再是最大值了,此时a已经没有了任何作用,a从队首出队。在a之前还有a-1,a-2......他们能影响的范围比a还要小,更不可能成为最大值,所以同理他们也从队首出队。一直到队列为空,现在b为新的最大值,为队首。
4、b<a:b更小,所以b没办法取代a,但是b有可能在a影响不到的地方也就是b+k-1这个点成为新的最大值,所以我们让b从队尾入队,可以理解为“待使用”。这里要注意的是b从队尾入队的时候也要遵循3中的原则,所以如果b比队尾元素大,那队尾元素也没有用了,我们也是将队尾元素出队,一直到b比队尾元素小停止。
5、还需要注意的一点是,滑动窗口是有大小的,所以我们队列中的元素是有“生命周期”的,也就是当前下标-队列元素下标+1要小于等于k
所以我们实际上队列存的是下标,这样引用起来比较方便。
代码
1 #include <iostream>
2 #include <algorithm>
3 using namespace std;
4 //这题是滑动窗口找最大或最小值的问题
5 //要运用到双头单调队列,一直维护最大或最小值,并且由于是滑动窗口所以元素存在生命周期,这里用数组q模拟
6 //
7 int num[1000010];
8 int q[4000020];
9 int main()
10 {
11 ios_base::sync_with_stdio(false);
12 cin.tie(NULL);cout.tie(NULL);
13 //
14 int n, k;cin >> n >> k;
15 for(int i = 0;i < n;++i) cin >> num[i];
16 //
17 int head, tail;
18 //最小值
19 head = 0, tail = 0;
20 //先让第一个元素入队
21 q[head] = 0;
22 for(int i = 0;i < n;++i)
23 {
24 //如果队首元素达到了生命周期,那么队首元素出队直到头尾指针相遇
25 while(head <= tail && i-q[head]+1 > k) head++;
26 if(num[q[head]] >= num[i])
27 {
28 //如果说你比这个队首元素还要小,那么一直出队
29 while(head <= tail && num[q[head]] >= num[i]) head++;
30 //走多了一格,要回去一格
31 q[--head] = i;
32 }else
33 {
34 //否则从队尾入队,但要维护单调性
35 while(head < tail && num[q[tail]] >= num[i]) tail--;
36 q[++tail] = i;
37 }
38 //当且仅当你达到所求滑动窗口大小的时候才能输出
39 if(i >= k-1) printf("%d ", num[q[head]]);
40 }
41 printf("\n");
42 //最大值
43 head = 0, tail = 0;
44 q[head] = 0;
45 for(int i = 0;i < n;++i)
46 {
47 while(head <= tail && i-q[head]+1 > k) head++;
48 if(num[q[head]] <= num[i])
49 {
50 while(head <= tail && num[q[head]] <= num[i]) head++;
51 q[--head] = i;
52 }else
53 {
54 while(head < tail && num[q[tail]] <= num[i]) tail--;
55 q[++tail] = i;
56 }
57 if(i >= k-1) printf("%d ", num[q[head]]);
58 }
59 printf("\n");
60 return 0;
61 }
62 //
2022GDUT寒训专题一I题的更多相关文章
- 2022GDUT寒训专题一J题
题目 题面 给你一个长度为 n的整数序列{A1,A2,⋯,A**n},要求从中找出一段连续的长度不超过 m的非空子序列,使得这个序列的和最大. 输入格式 第一行为两个整数 n,m: 第二行为 n个用空 ...
- 2022GDUT寒训专题一C题
题目 题面 马在中国象棋以日字形规则移动. 请编写一段程序,给定n×m大小的棋盘,以及马的初始位置 (x, y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点. 输入格式 ...
- X-NUCA 2017 web专题赛训练题 阳光总在风雨后和default wp
0X0.前言 X-NUCA 2017来了,想起2016 web专题赛,题目都打不开,希望这次主办方能够搞好点吧!还没开赛,依照惯例会有赛前指导,放一些训练题让CTFer们好感受一下题目. 题目有一大 ...
- 专题:DP杂题1
A POJ 1018 Communication System B POJ 1050 To the Max C POJ 1083 Moving Tables D POJ 1125 Stockbroke ...
- 恶补一下DP+背包专题(刷刷水题)L2
开心的金明 题目大意 就是求一定背包容量的最大值 思路 想必大家都知道,一看到这种题目,就会想起01背包 虽然特别简单但是还是讲一下吧 状态设置 由于这题差不多是一个01背包的版子题,那么我们就只需要 ...
- 7专题总结-高频题high frequency
Outline . Single Number I, II, III . Majority Number I, II, III . Best Time to Buy and Sale Stock I, ...
- 多校寒训TaoTao要吃鸡dp
题目描述 Taotao的电脑带不动绝地求生,所以taotao只能去玩pc版的荒野行动了, 和绝地求生一样,游戏人物本身可以携带一定重量m的物品,装备背包 之后可以多携带h(h为0代表没有装备背包)重量 ...
- 最小生成树 kuangbin专题最后一个题
题目链接:https://cn.vjudge.net/contest/66965#problem/N 注释:这道题需要用krustra,用prim的话可能会超时.并且在计算距离的时候要尽量减少步骤,具 ...
- 专题练习HDU题集 图论
[图论01]最短路 Start Time : 2018-01-02 12:45:00 End Time : 2018-01-23 12:45:00 Contest Status : Runnin ...
随机推荐
- bootstrap栅格例子
<div class="container-fluid "> <div class="row"> <div class=" ...
- 客户通过新型网络访问Web服务
- JSR310-LocalDateTime序列化 & 反序列化
问题 springboot 版本:spring-boot 2.3.12 今天在开发一个redis 热key服务端的过程中,碰到2个问题: jdk8的LocalDateTime,LocalDate,Lo ...
- 『学了就忘』Linux日志管理 — 92、日志轮替
目录 1.日志文件的命名规则 2.logrotate配置文件说明 3.logrotate配置文件的主要参数 1.日志文件的命名规则 日志轮替最主要的作用就是把旧的日志文件移动并改名,同时建立新的空日志 ...
- Linux使用docker安装Jenkins 并进行jar包发布
拉取镜像 docker pull jenkins/jenkins:lts 创建docker-compose.yml 文件 (主要习惯 也可以不用这种方式) Linux安装docker-compose ...
- 聊一下 TS 中的交叉类型
交叉类型不能完全按照传统编程中的 与 来理解. 交叉类型的定义:将多个类型合并为一个类型,包含了所有类型的特性,而且要同时满足要交叉的所有类型. 后半段话不是很好理解,看一下接口类型和联合类型的交叉类 ...
- chrome/microsoft/brave等浏览器离线下载crx并安装(解决download interrupted)
重要网站 离线下载crx 问题描述 使用chrome/microsoft edge/ brave 下载chrome webstroe插件时,提示: download interrupted. 解决方案 ...
- 【LeetCode】962. Maximum Width Ramp 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 单调栈 日期 题目地址:https://leetco ...
- hdu 5592 ZYB's Premutation(线段树优化)
设f_ifi是第ii个前缀的逆序对数,p_ipi是第ii个位置上的数,则f_i-f_{i-1}fi−fi−1是ii前面比p_ipi大的数的个数.我们考虑倒着做,当我们处理 ...
- CAS学习笔记一:CAS 授权服务器简易搭建
什么是CAS CAS是Central Authentication Service的缩写,中央认证服务,一种独立开放指令协议.CAS 是 耶鲁大学(Yale University)发起的一个开源项目, ...