zoukankan      html  css  js  c++  java
  • 18.12.16 滑动窗口(单调队列)

    描述

    给定一个长度为n(n<=10^6)的数组。有一个大小为k的滑动窗口从数组的最左端移动到最右端。你可以看到窗口中的k个数字。窗口每次向右滑动一个数字的距离。
    下面是一个例子:
    数组是 [1 3 -1 -3 5 3 6 7], k = 3。

    窗口位置最小值最大值
    [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


    你的任务是得到滑动窗口在每个位置时的最大值和最小值。

     

    输入

    输入包括两行。
    第一行包括n和k,分别表示数组的长度和窗口的大小。
    第二行包括n个数字。输出输出包括两行。
    第一行包括窗口从左至右移动的每个位置的最小值。
    第二行包括窗口从左至右移动的每个位置的最大值。

    样例输入

    8 3
    1 3 -1 -3 5 3 6 7

    样例输出

    -1 -3 -3 -3 3 3 3 3 5 5 6 7

     1 #include <iostream>
     2 #include <string.h>
     3 #include <algorithm>
     4 #include <stack>
     5 #include <string>
     6 #include <math.h>
     7 #include <queue>
     8 #include <stdio.h>
     9 #include <string.h>
    10 #include <vector>
    11 #include <fstream>
    12 #define maxn 1000005
    13 #define inf 999999
    14 #define cha 127
    15 using namespace std;
    16 
    17 struct node {
    18     int p, val;
    19     node(int a, int b) {
    20         p = a, val = b;
    21     }
    22 };
    23 deque<node>minq;
    24 deque<node>maxq;
    25 int n, k;
    26 int imin, imax;
    27 
    28 void insert(node val,int first) {
    29     
    30     while (!minq.empty() &&minq.back().val >= val.val)
    31         minq.pop_back();
    32     minq.push_back(val);
    33     while ( minq.front().p < first)
    34         minq.pop_front();
    35     while (!maxq.empty() &&maxq.back().val <= val.val)
    36         maxq.pop_back();
    37     maxq.push_back(val);
    38     while ( maxq.front().p < first)
    39         maxq.pop_front();
    40 }
    41 
    42 int minans[maxn], maxans[maxn];
    43 void init() {
    44     scanf("%d%d", &n, &k);
    45     int tmp;
    46     for (int i = 1; i <= k - 1; i++) {
    47         scanf("%d", &tmp);
    48         insert(node(i, tmp),1);
    49     }
    50     for (int i = k; i <= n; i++) {
    51         int l = i - k + 1;
    52         scanf("%d", &tmp);
    53         insert(node(i, tmp), l);
    54         minans[++imin] = minq.front().val;
    55         maxans[++imax] = maxq.front().val;
    56     }
    57     printf("%d", minans[1]);
    58     for (int i = 2; i <= imin; i++)
    59         printf(" %d", minans[i]);
    60     printf("
    ");
    61     printf("%d", maxans[1]);
    62     for (int i = 2; i <= imax; i++)
    63         printf(" %d", maxans[i]);
    64     printf("
    ");
    65 }
    66 
    67 int main()
    68 {
    69     init();
    70     return 0;
    71 }
    View Code

    上面是1k4ms样子过的,但我就很奇怪我写的另一个相似版本tle:

     1 #include <iostream>
     2 #include <string.h>
     3 #include <algorithm>
     4 #include <stack>
     5 #include <string>
     6 #include <math.h>
     7 #include <queue>
     8 #include <stdio.h>
     9 #include <string.h>
    10 #include <vector>
    11 #include <fstream>
    12 #define maxn 1000005
    13 #define inf 999999
    14 #define cha 127
    15 using namespace std;
    16 
    17 struct node {
    18     int p, val;
    19     node(int a, int b) {
    20         p = a, val = b;
    21     }
    22 };
    23 deque<node>minq;
    24 deque<node>maxq;
    25 int n, k;
    26 int imin, imax;
    27 
    28 void insert(node val,int first) {
    29     while (!minq.empty() && minq.front().p < first)
    30         minq.pop_front();
    31     while (!maxq.empty() && maxq.front().p < first)
    32         maxq.pop_front();
    33     for (int i = minq.size() - 1; i >= 0; i--) {
    34         if (minq[i].val >= val.val)
    35             minq.pop_back();
    36     }
    37     minq.push_back(val);
    38     for (int i = maxq.size() - 1; i >= 0; i--) {
    39         if (maxq[i].val <= val.val)
    40             maxq.pop_back();
    41     }
    42     maxq.push_back(val);
    43 }
    44 
    45 int minans[maxn], maxans[maxn];
    46 void init() {
    47     scanf("%d%d", &n, &k);
    48     int tmp;
    49     for (int i = 1; i <= k - 1; i++) {
    50         scanf("%d", &tmp);
    51         insert(node(i, tmp),1);
    52     }
    53     for (int i = k; i <= n; i++) {
    54         int l = i - k + 1;
    55         scanf("%d", &tmp);
    56         insert(node(i, tmp), l);
    57         minans[++imin] = minq.front().val;
    58         maxans[++imax] = maxq.front().val;
    59     }
    60     printf("%d", minans[1]);
    61     for (int i = 2; i <= imin; i++)
    62         printf(" %d", minans[i]);
    63     printf("
    ");
    64     printf("%d", maxans[1]);
    65     for (int i = 2; i <= imax; i++)
    66         printf(" %d", maxans[i]);
    67     printf("
    ");
    68 }
    69 
    70 int main()
    71 {
    72     init();
    73     return 0;
    74 }
    View Code

    感觉也没调用什么……顺序改变了一下。我发现我写的程序都好慢啊……写lab的时候就体会到了,我的程序总是跑很慢|||

    单调队列

    用deque比较容易实现

    维护区间最值

    主要操作是每次加入新值删除队头冗余值,并且删去队尾所有比新值小的值,使得整个队总是单调

    性能是O(n)

    那么问题来了,一个没有竞赛过的菜鸡怎么在考试的时候知道这些??

    注定失败的战争,也要拼尽全力去打赢它; 就算输,也要输得足够漂亮。
  • 相关阅读:
    乌龟棋
    Cut the Sequence
    [NOI2001]炮兵阵地
    Fence
    环路运输
    查找并替换字符串 Find And Replace in String
    最大交换 Maximum Swap
    丑数问题 Ugly Number
    二叉树最大宽度 Maximum Width of Binary Tree
    距离为K的节点 All Nodes Distance K in Binary Tree
  • 原文地址:https://www.cnblogs.com/yalphait/p/10126726.html
Copyright © 2011-2022 走看看