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 ...
随机推荐
- Linux使用docker安装RabbitMQ
拉取镜像 docker pull rabbitmq:management 启动容器 docker run -d --name rabbitmq -e RABBITMQ_DEFAULT_USER=adm ...
- c++使用map保存成员函数地址
note 本基于c++11介绍一种使用map保存成员函数地址 可避免使用 if 和 switch 配置灵活 方便, 代码维护效率高 结果: 范例开始 头文件包含 #include <iostre ...
- 【LeetCode】364. Nested List Weight Sum II 解题报告 (C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 日期 题目地址:https://leetcode ...
- 【LeetCode】657. Robot Return to Origin 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 复数求和 counter统计次数 相似题目 参考资料 ...
- html简单随机抽奖页面(在线抽奖、随机选取、自动挑选)
下载: https://download.csdn.net/download/weixin_44893902/20366745 效果: 代码: <!doctype html> <ht ...
- 编写Java程序,随机给定一个数字猜大小
返回本章节 返回作业目录 需求说明: 由系统随机生成一个1~100之间的整数. 通过控制台一直输入一个整数,比较该数与系统随机生成的那个数,如果大就输出"猜大了.",继续输入:如果 ...
- Ubuntu18.04安装/卸载NVIDIA显卡驱动
1 显卡驱动下载 官网:NVIDIA 搜索适合本机的驱动 获取最新版本驱动 立即下载 文件 以上,显卡驱动下载完成. 2 显卡驱动安装 2.1 添加可执行权限 进入驱动文件目录sudo chmod a ...
- 实践剖析.NET Core如何支持Cookie和JWT混合认证、授权
前言 为防止JWT Token被窃取,我们将Token置于Cookie中,但若与第三方对接,调用我方接口进行认证.授权此时仍需将Token置于请求头,通过实践并联系理论,我们继续开始整活!首先我们实现 ...
- 深入 Laravel 内核之外观模式(门面模式)
门面模式核心内容: 客户端与子系统的通信通过外观对象进行: 外观对象封装一系列子系统的具体对应方法,对客户端只需暴露一个单一的入口方法: 客户端通过访问外观对象即可调用子系统的基础方法,无需关心子系统 ...
- monkey怎么做APP自动化?
前言: monkey是andriod平台自动化测试的一种手段,通过monkey程序模拟触摸屏幕.滑动,滚屏,按键来对设备进行压力测试,检测程序多久会出现异常第一种:设置好命令,做随机自动化 什么时候可 ...