#pragma once

#include <iostream>
#include <vector>
#include <deque>
#include <iostream>
#include <hack/logger/logger.hpp>

namespace alg::tasks
{
  // Рассмотрим последовательность целых чисел длины n. 
  // По ней двигается «окно» длины k: сначала в «окне» находятся 
  // первые k чисел, на следующем шаге в «окне» уже будут находиться 
  // k чисел, начиная со второго, и так далее до конца последовательности.
  // Требуется для каждого положения «окна» определить минимум в нём.
  /* пример:
     7 3
     1 3 2 4 5 3 1

     Рассмотрим все доступные положения скользящего окна:
     |1 3 2| 4 5 3 1 - min(1, 3, 2) = 1
     1 |3 2 4| 5 3 1 - min(3, 2, 4) = 2
     1 3 |2 4 5| 3 1 - min(2, 4, 5) = 2
     1 3 2 |4 5 3| 1 - min(4, 5, 3) = 3
     1 3 2 4 |5 3 1| - min(5, 3, 1) = 1

     результат [1, 2, 2, 3, 1]
  */
  inline void run_002()
  {
    // Ускоряем ввод/вывод для больших объёмов данных
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, k;
    std::cin >> n >> k;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++i) std::cin >> a[i];

    // deque хранит индексы элементов текущих окон.
    // Значения a[dq[0]], a[dq[1]], ... всегда идут в неубывающем порядке.
    std::deque<int> dq;

    for (int i = 0; i < n; ++i) 
    {
      // 1. Удаляем индекс из начала, если он вышел за пределы окна
      if (!dq.empty() && dq.front() == i - k) dq.pop_front();

      // 2. Удаляем индексы с конца, если их значения >= текущего элемента.
      // Они больше никогда не станут минимумом окна.
      while (!dq.empty() && a[dq.back()] >= a[i]) dq.pop_back();

      // 3. Добавляем текущий индекс
      dq.push_back(i);

      // 4. Если окно полностью сформировалось (прошли минимум k элементов),
      // минимум всегда находится в начале deque.
      if (i >= k - 1) std::cout << a[dq.front()] << '\n';
    }
  }
}

/*
  Основное:
  1. **`dq.front()`** всегда содержит индекс минимального элемента в текущем окне.
  2. При сдвиге окна мы удаляем устаревший индекс слева (`i - k`).
  3. Перед добавлением нового элемента мы "очищаем" хвост очереди от элементов, которые больше или равны новому. 
     Они бесполезны, так как новый элемент `a[i]` моложе (живёт дольше в окне) и не больше их, поэтому минимумом они стать не смогут.
  4. Каждый элемент добавляется в `deque` ровно один раз и удаляется тоже не более одного 
     раза → **амортизированное время `O(1)` на шаг**, итого `O(n)` на всю последовательность.

     Сложность:
     - **Время:** `O(n)` (проход по массиву, каждое число добавляется/удаляется из `deque` максимум 1 раз)
     - **Память:** `O(n)` для хранения массива + `O(k)` для `deque` (в худшем случае)

     Примечание по вводу/выводу:
     В коде использованы `ios_base::sync_with_stdio(false); cin.tie(nullptr);` и `'\n'` вместо `endl`. 
     Это критически важно для задач с `n > 10^5`, иначе программа может не уложиться в лимит времени из-за медленного I/O в C++.
*/
