• [LG1886]滑动窗口 单调队列


    ~~~题面~~~

    题解:

      观察数据范围,这应该是一个复杂度O(n)的题。以最大值为例,考虑单调队列,维护一个单调递减的队列。从前向后扫,每次答案取队首,如果后面进入的比前面大,那么就弹出前面的数,因为是从前向后扫,所以后面进入的如果比前面的大,那么一定更优,因为要淘汰肯定先淘汰前面的。如果队首已经不在当前窗口内了,那么就弹出,直到合法为止。

      维护单调队列时的一个重要原则就是把别人“挤掉”的元素一定要比被挤掉的元素更优,否则可能找不到合法情况or漏掉最优解。注意这一点就很好理解了。

      最小值用求最大值相反的操作即可

      不知道为什么我以前写代码写那么丑,,,,重新写一份好了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define R register int
     4 #define AC 1001000
     5 
     6 int n, k, head, tail;
     7 int s[AC];
     8 struct node{
     9     int x, id;
    10 }q[AC];
    11 
    12 inline int read()
    13 {
    14     int x = 0;char c = getchar(); bool z = false;
    15     while(c > '9' || c < '0')
    16     {
    17         if(c == '-') z = true;
    18         c = getchar();
    19     }
    20     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    21     if(!z) return x;
    22     else return -x;
    23 }
    24 
    25 void pre()
    26 {
    27     n = read(), k = read();
    28     for(R i = 1; i <= n; i ++) s[i] = read();
    29 }
    30 
    31 void work1()
    32 {
    33     head = 1, tail = 0;
    34     for(R i = 1; i <= n; i ++)
    35     {
    36         while(head <= tail && q[head].id <= i - k) ++ head;
    37         while(s[i] < q[tail].x && head <= tail) -- tail;//可以删完,反正后面要塞进来
    38         q[++tail] = (node){s[i], i};
    39         if(i >= k) printf("%d ", q[head].x);
    40     }    
    41     printf("
    ");    
    42 }
    43 
    44 void work2()
    45 {
    46     head = 1, tail = 0;
    47     for(R i = 1; i <= n; i ++)
    48     {
    49         while(head <= tail && q[head].id <= i - k) ++ head;//,,,前面也可以删完
    50         while(s[i] > q[tail].x && head <= tail) -- tail;//可以删完,反正后面要塞进来
    51         q[++tail] = (node){s[i], i};
    52         if(i >= k) printf("%d ", q[head].x);
    53     }    
    54     printf("
    ");
    55 }
    56 
    57 int main()
    58 {
    59     freopen("in.in", "r", stdin);
    60     pre();
    61     work1();
    62     work2();
    63     fclose(stdin);
    64     return 0;
    65 }
    View Code

       当然如果你喜欢简短的代码,且不在意常数问题,你也可以这么写:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define R register int
     4 #define AC 1001000
     5 
     6 int n, k, head, tail;
     7 int s[AC];
     8 struct node{ int x, id;} q[AC];
     9 
    10 void cal(int t)
    11 {
    12     head = 1, tail = 0;
    13     for(R i = 1; i <= n; i ++)
    14     {
    15         while(head <= tail && q[head].id <= i - k) ++ head;
    16         while(s[i] < q[tail].x && head <= tail) -- tail;//可以删完,反正后面要塞进来
    17         q[++tail] = (node){s[i], i};
    18         if(i >= k) printf("%d ", q[head].x * t);
    19     }printf("
    ");    
    20 }
    21 
    22 int main()
    23 {
    24     scanf("%d%d", &n, &k);
    25     for(R i = 1; i <= n; i ++) scanf("%d", &s[i]);
    26     cal(1);
    27     for(R i = 1; i <= n; i ++) s[i] = -s[i];
    28     cal(-1);
    29     return 0;
    30 }
    View Code
  • 相关阅读:
    python 解释器交互模块 -- sys
    python 操作系统模块 -- OS
    python 随机数模块 -- random
    python 时间模块 -- time
    Python 面向对象
    python 模块
    python -- 面向对象进阶
    github连接提示
    linux day4
    git基本使用
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9780397.html
Copyright © 2020-2023  润新知