单调队列

204 阅读1分钟
  • 常见模型:找出滑动窗口中的最大值/最小值

模板

  • C++
int hh = 0, tt = -1;
for (int i = 0; i < n; i ++ )
{
    while (hh <= tt && check_out(q[hh])) hh ++ ;  // 判断队头是否滑出窗口
    while (hh <= tt && check(q[tt], i)) tt -- ;
    q[ ++ tt] = i;
}
  • Java
int hh = 0;
int tt = -1;
for (int i = 0; i < n; i ++) {
    while (hh <= tt && check_out(q[hh])) {  // 判断队头是否滑出窗口
        h++;
    }
    while (hh <= tt && check(q[tt], i)) {
        tt--;
    }
    q[++tt] = i;
}

练习

01 滑动窗口

  • 题目

Snipaste_2023-03-01_23-05-23.png

  • 题解
import java.io.*;

public class Main {
    public static final int N = 1000010;
    public static int[] a = new int[N];
    public static int[] q = new int[N];
    public static int hh, tt, n, k;

    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
        String[] str1 = br.readLine().split(" ");
        n = Integer.parseInt(str1[0]);
        k = Integer.parseInt(str1[1]);
        String[] str2 = br.readLine().split(" ");
        for (int i = 0; i < n; i++) {
            a[i] = Integer.parseInt(str2[i]);
        }

        hh = 0;
        tt = -1;
        for (int i = 0; i < n; i++) {
            if (hh <= tt && i - k + 1 > q[hh]) {
                hh++;
            }
            while (hh <= tt && a[q[tt]] >= a[i]) {
                tt--;
            }
            q[++tt] = i;
            if (i >= k - 1) {
                pw.print(a[q[hh]] + " ");
            }
        }
        pw.println();

        hh = 0;
        tt = -1;
        for (int i = 0; i < n; i++) {
            if (hh <= tt && i - k + 1 > q[hh]) {
                hh++;
            }
            while (hh <= tt && a[q[tt]] <= a[i]) {
                tt--;
            }
            q[++tt] = i;
            if (i >= k - 1) {
                pw.print(a[q[hh]] + " ");
            }
        }

        pw.close();
        br.close();
    }
}