~~~题面~~~

题解:

  观察数据范围,这应该是一个复杂度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("\n");    
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("\n");
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

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-01-13
  • 2021-10-16
  • 2021-11-17
  • 2021-07-15
猜你喜欢
  • 2021-02-21
  • 2021-12-30
  • 2022-02-28
  • 2021-08-11
  • 2021-09-10
  • 2021-06-04
  • 2022-12-23
相关资源
相似解决方案