题目

题面

给一个长度为 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题的更多相关文章

  1. 2022GDUT寒训专题一J题

    题目 题面 给你一个长度为 n的整数序列{A1,A2,⋯,A**n},要求从中找出一段连续的长度不超过 m的非空子序列,使得这个序列的和最大. 输入格式 第一行为两个整数 n,m: 第二行为 n个用空 ...

  2. 2022GDUT寒训专题一C题

    题目 题面 马在中国象棋以日字形规则移动. 请编写一段程序,给定n×m大小的棋盘,以及马的初始位置 (x, y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点. 输入格式 ...

  3. X-NUCA 2017 web专题赛训练题 阳光总在风雨后和default wp

     0X0.前言 X-NUCA 2017来了,想起2016 web专题赛,题目都打不开,希望这次主办方能够搞好点吧!还没开赛,依照惯例会有赛前指导,放一些训练题让CTFer们好感受一下题目. 题目有一大 ...

  4. 专题:DP杂题1

    A POJ 1018 Communication System B POJ 1050 To the Max C POJ 1083 Moving Tables D POJ 1125 Stockbroke ...

  5. 恶补一下DP+背包专题(刷刷水题)L2

    开心的金明 题目大意 就是求一定背包容量的最大值 思路 想必大家都知道,一看到这种题目,就会想起01背包 虽然特别简单但是还是讲一下吧 状态设置 由于这题差不多是一个01背包的版子题,那么我们就只需要 ...

  6. 7专题总结-高频题high frequency

    Outline . Single Number I, II, III . Majority Number I, II, III . Best Time to Buy and Sale Stock I, ...

  7. 多校寒训TaoTao要吃鸡dp

    题目描述 Taotao的电脑带不动绝地求生,所以taotao只能去玩pc版的荒野行动了, 和绝地求生一样,游戏人物本身可以携带一定重量m的物品,装备背包 之后可以多携带h(h为0代表没有装备背包)重量 ...

  8. 最小生成树 kuangbin专题最后一个题

    题目链接:https://cn.vjudge.net/contest/66965#problem/N 注释:这道题需要用krustra,用prim的话可能会超时.并且在计算距离的时候要尽量减少步骤,具 ...

  9. 专题练习HDU题集 图论

    [图论01]最短路 Start Time : 2018-01-02 12:45:00    End Time : 2018-01-23 12:45:00 Contest Status : Runnin ...

随机推荐

  1. STL源码剖析-waked_ptr

    目录一.提问二. 代码实现2.1 mweak_ptr的具体实现2.2 测试用例一.提问weak_ptr为什么会存在?shared_ptr不是已经有了引用计数吗?具体原因详见模拟实现boost库中的sh ...

  2. MySQL 报错:[Err] 1071 - Specified key was too long; max key length is 767 bytes

    [Err] 1071 - Specified key was too long; max key length is 767 bytes 这个会出现在MySQ5.7以下版本 因为没有启用innodb_ ...

  3. IDEA设置调用方法时提示方法上的注释

    IDEA设置代码注释提示,代码提示,鼠标放上面提示方法的注解信息 打开file-->setting-->Editor-->General,将Show quick documentat ...

  4. 【LeetCode】214. Shortest Palindrome 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 前缀是否回文 判断前缀 相似题目 参考资料 日期 题 ...

  5. 【LeetCode】563. Binary Tree Tilt 解题报告(Java & Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 Java解法 Python解法 日期 题目地址:ht ...

  6. 【LeetCode】787. Cheapest Flights Within K Stops 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:DFS 方法二:BFS 参考资料 日期 题目 ...

  7. 【LeetCode】162. Find Peak Element 解题报告(Python)

    [LeetCode]162. Find Peak Element 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/ ...

  8. 【LeetCode】816. Ambiguous Coordinates 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.me/ 题目地址:https://leetcode.com/problems/ambiguous ...

  9. hdu-5568SUM (dp)

    sequence2 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  10. Java 泛型通配符 T,E,K,V,?

    Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许开发者在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说所操作的数据类型被 ...