#include <iostream>
#include <stack>
#include <algorithm>
#include <cstdint>
#include <vector>
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
template <typename T>
constexpr T popCount(const T u)
{
#ifdef __has_builtin
    return u == 0 ? T(0) : (T)__builtin_popcountll(u);
#else
    unsigned long long v = static_cast<unsigned long long>(u);
    return v = (v & 0x5555555555555555ULL) + (v >> 1 & 0x5555555555555555ULL), v = (v & 0x3333333333333333ULL) + (v >> 2 & 0x3333333333333333ULL), v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL, static_cast<T>(v * 0x0101010101010101ULL >> 56 & 0x7f);
#endif
}
template <typename T>
constexpr T log2p1(const T u)
{
#ifdef __has_builtin
    return u == 0 ? T(0) : T(64 - __builtin_clzll(u));
#else
    unsigned long long v = static_cast<unsigned long long>(u);
    return v = static_cast<unsigned long long>(v), v |= (v >> 1), v |= (v >> 2), v |= (v >> 4), v |= (v >> 8), v |= (v >> 16), v |= (v >> 32), popCount(v);
#endif
}
template <typename T>
constexpr T clog(const T v) { return v == 0 ? T(0) : log2p1(v - 1); }
template <typename T>
constexpr T msbp1(const T v) { return log2p1(v); }
template <typename T>
constexpr T lsbp1(const T v)
{
#ifdef __has_builtin
    return __builtin_ffsll(v);
#else
    return v == 0 ? T(0) : popCount((v & (-v)) - T(1)) + T(1);
#endif
}
template <typename T>
constexpr bool ispow2(const T v) { return popCount(v) == 1; }
template <typename T>
constexpr T ceil2(const T v) { return v == 0 ? T(1) : T(1) << log2p1(v - 1); }
template <typename T>
constexpr T floor2(const T v) { return v == 0 ? T(0) : T(1) << (log2p1(v) - 1); }
//!====================================================================================================!//
//!  .d88888b                                                  d888888P          dP       dP           !//
//!  88.    "'                                                    88             88       88           !//
//!  'Y88888b. 88d888b. .d8888b. 88d888b. .d8888b. .d8888b.       88    .d8888b. 88d888b. 88 .d8888b.  !//
//!        '8b 88'  '88 88'  '88 88'  '88 Y8ooooo. 88ooood8       88    88'  '88 88'  '88 88 88ooood8  !//
//!  d8'   .8P 88.  .88 88.  .88 88             88 88.  ...       88    88.  .88 88.  .88 88 88.  ...  !//
//!   Y88888P  88Y888P' '88888P8 dP       '88888P' '88888P'       dP    '88888P8 88Y8888' dP '88888P'  !//
//!            88                                                                                      !//
//!            dP                                                                                      !//
//!====================================================================================================!//
template <typename Base>
class SparseTable
{
public:
    using T = typename Base::T;
    using SemiLattice = Base;
    template <typename InIt>
    SparseTable(const InIt first, const InIt last) : size(std::distance(first, last)), lg2(size + 1, 0)
    {
        std::vector<T> val{first, last};
        for (std::size_t i = 2; i <= size; i++) { lg2[i] = lg2[i / 2] + 1; }
        table.resize(size, std::vector<T>(lg2[size] + 1));
        for (std::size_t i = 0; i < size; i++) { table[i][0] = val[i]; }
        for (std::size_t j = 0; j < lg2[size]; j++) {
            for (std::size_t i = 0, w = 1 << j; i <= size - (w << 1); i++) { table[i][j + 1] = op(table[i][j], table[i + w][j]); }
        }
    }
    T accumulate(const std::size_t l, const std::size_t r) const
    {
        const std::size_t j = lg2[r - l];
        return op(table[l][j], table[r - (1 << j)][j]);
    }

private:
    const std::size_t size;
    std::vector<std::size_t> lg2;
    std::vector<std::vector<T>> table;
    const SemiLattice op{};
};
//!====================================================================================!//
//!  .d88888b    dP              dP   oo            888888ba  8888ba.88ba   .88888.    !//
//!  88.    "'   88              88                 88    '8b 88  '8b  '8b d8'   '8b   !//
//!  'Y88888b. d8888P .d8888b. d8888P dP .d8888b.  a88aaaa8P' 88   88   88 88     88   !//
//!        '8b   88   88'  '88   88   88 88'  '""   88   '8b. 88   88   88 88  db 88   !//
//!  d8'   .8P   88   88.  .88   88   88 88.  ...   88     88 88   88   88 Y8.  Y88P   !//
//!   Y88888P    dP   '88888P8   dP   dP '88888P'   dP     dP dP   dP   dP  '8888PY8b  !//
//!====================================================================================!//
template <typename Type, typename B = uint64_t>
class StaticRMQ
{
    static constexpr std::size_t L = sizeof(B) * 8;

public:
    template <typename InIt>
    StaticRMQ(const InIt first, const InIt last) : N{std::size_t(std::distance(first, last))}, M{(N + L - 1) / L}, v(N), blocks(M), masks(N, 0)
    {
        std::copy(first, last, v.begin());
        for (std::size_t i = 0; i < N; i++) { blocks[i / L] = i % L == 0 ? v[i] : std::min(blocks[i / L], v[i]); }
        for (std::size_t i = 0; i < M; i++) {
            std::vector<std::size_t> g(L, N);
            std::stack<std::size_t> stack;
            for (std::size_t j = 0; j < L and i * L + j < N; j++) {
                for (; not stack.empty() and v[stack.top()] >= v[i * L + j]; stack.pop()) {}
                g[j] = stack.empty() ? N : stack.top(), stack.push(i * L + j);
            }
            for (std::size_t j = 0; j < L and i * L + j < N; j++) { masks[i * L + j] = g[j] == N ? B(0) : (masks[g[j]] | B(1) << (g[j] - i * L)); }
        }
    }
    Type accumulate(const std::size_t l, const std::size_t r) const
    {
        static const SparseTable<Min> stable(blocks.begin(), blocks.end());
        const std::size_t LB = (l + L - 1) / L, RB = r / L;
        if (LB > RB) {
            return internal(l, r);
        } else {
            return LB < RB ? (l < L * LB ? (L * RB < r ? std::min({stable.accumulate(LB, RB), internal(l, L * LB), internal(L * RB, r)}) : std::min(stable.accumulate(LB, RB), internal(l, L * LB))) : (L * RB < r ? std::min(stable.accumulate(LB, RB), internal(L * RB, r)) : stable.accumulate(LB, RB))) : (l < L * LB ? (L * RB < r ? std::min(internal(l, L * LB), internal(L * RB, r)) : internal(l, L * LB)) : (L * RB < r ? internal(L * RB, r) : Type{}));
        }
    }

private:
    struct Min
    {
        using T = Type;
        T operator()(const T& a, const T& b) const { return std::min(a, b); }
    };
    Type internal(const std::size_t l, std::size_t r) const
    {
        r--;
        const B w = masks[r] >> (l % L);
        return w == 0 ? v[r] : v[l + lsbp1(w) - 1];
    }
    const std::size_t N, M;
    std::vector<Type> v, blocks;
    std::vector<B> masks;
};
int main()
{
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    std::size_t N, L;
    std::cin >> N >> L;
    std::vector<ll> A(N);
    for (std::size_t i = 0; i < N; i++) { std::cin >> A[i]; }
    StaticRMQ<ll> rmq(A.begin(), A.end());
    for (std::size_t i = 0; i + L <= N; i++) { std::cout << (i == 0 ? "" : " ") << rmq.accumulate(i, i + L); }
    std::cout << "\n";
    return 0;
}



Measured memory_bytes: 29012