滑动窗口

https://www.acwing.com/problem/content/156/
image.png
image.png
思考:
1.暴力怎么做
2.队列当中有没有无用的值,怎么去掉
3.删掉多余的值,构造单调性
4.有了单调性,就有了极值,就优化了问题

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N = 1e6 + 10;
  4. int a[N], q[N], n, k;
  5. int hh, tt;
  6. int main(){
  7. cin >> n >> k;
  8. for (int i = 0; i < n; i++) scanf("%d", &a[i]);
  9. hh = 0, tt = -1;
  10. for (int i = 0; i < n; i++){
  11. // 窗口滑出去了
  12. if (hh <= tt && i - k + 1 > q[hh]) hh++;
  13. // 较小的值入队
  14. while (hh <= tt && a[q[tt]] >= a[i]) tt--;
  15. q[++tt] = i;
  16. // 窗口是满的就输出,没满k宽度的时候,是不可输出的
  17. // 队列是单调递增的,队头是窗口里的最小值
  18. if (i - k + 1 >= 0) printf("%d ", a[q[hh]]);
  19. }
  20. puts("");
  21. hh = 0, tt = -1;
  22. for (int i = 0; i < n; i++){
  23. // 窗口滑出去了
  24. if (hh <= tt && i - k + 1 > q[hh]) hh++;
  25. // 较小的值入队
  26. while (hh <= tt && a[q[tt]] <= a[i]) tt--;
  27. q[++tt] = i;
  28. // 窗口是满的就输出,没满k宽度的时候,是不可输出的
  29. if (i - k + 1 >= 0) printf("%d ", a[q[hh]]);
  30. }
  31. puts("");
  32. return 0;
  33. }