#include <bits/stdc++.h>
#define GET_REP(_1, _2, _3, NAME, ...) NAME
#define rep(...) GET_REP(__VA_ARGS__, irep, _rep)(__VA_ARGS__)
#define rep1(...) GET_REP(__VA_ARGS__, irep1, _rep1)(__VA_ARGS__)
#define _rep(i, n) irep (i, 0, n)
#define _rep1(i, n) irep1(i, 1, n)
#define irep(i, a, n) for (int i = a; i < (int)(n); ++i)
#define irep1(i, a, n) for (int i = a; i <= (int)(n); ++i)
#define rrep(i, n) for (int i = (int)(n) - 1; i >= 0; --i)
#define rrep1(i, n) for (int i = (int)(n); i >= 1; --i)
#define allrep(X, x) for (auto &&X : x)
#define all(x) (x).begin(), (x).end()
#ifdef LOCAL
  #include "../../Lib/cout_container.hpp"
  #define debug(x) cerr << #x " => " << x << endl
#else
  #define debug(x) 0
#endif
using lint = long long;
constexpr int    INF  = 1 << 30;
constexpr lint   INFL = 1LL << 62;
constexpr int    MOD  = (int)1e9 + 7;
constexpr double EPS  = 1e-9;
using namespace std;
namespace { struct INIT { INIT() { cin.tie(0); ios::sync_with_stdio(false); cout << fixed << setprecision(15); } } INIT; }

template <typename T>
class RangeMinmaxQuery {
  template <typename C>
  struct Compare { bool operator()(const C &a, const C &b) const { return a < b; } };
  template <typename S>
  class SparseTable {
    Compare<S> comp;
    vector<vector<int>> st;
    vector<int> lookup;
    vector<S>   origin;

    public:
    SparseTable(void) {}
    SparseTable(const vector<S> &v) { init(v); }
    void init(const vector<S> &v) {
      origin = v;
      int lg_size = 0, v_size = v.size();
      while ((1 << lg_size) <= v_size) ++lg_size;
      st.assign((1 << lg_size), vector<int>(lg_size));
      for (int i = 0; i < v_size; ++i) st[i][0] = i;
      for (int j = 1; j < lg_size; ++j) {
        for (int i = 0; i + (1 << j) <= (1 << lg_size); ++i) {
          int l = st[i][j - 1], r = st[i + (1 << (j - 1))][j - 1];
          st[i][j] = comp(v[r], v[l]) ? r : l;
        }
      }
      lookup.assign(v_size + 1, 0);
      for (int i = 2; i <= v_size; ++i) lookup[i] = lookup[i >> 1] + 1;
    }
    S query(int l, int r) const {
      int lg_size = lookup[r - l];
      S   lret = origin[st[l][lg_size]], rret = origin[st[r - (1 << lg_size)][lg_size]];
      return comp(rret, lret) ? rret : lret;
    }
    int query_index(int l, int r) const {
      int lg_size = lookup[r - l];
      int lidx = st[l][lg_size], ridx = st[r - (1 << lg_size)][lg_size];
      return comp(origin[ridx], origin[lidx]) ? ridx : lidx;
    }
    int size(void) const { return st.size(); }
  };
  Compare<T> comp;
  int v_size, bl_size, bl_num;
  SparseTable<pair<T, int>> st;
  vector<int> bit;
  vector<T>   origin;
  static int lsb(const unsigned bit) {
    static constexpr int table[32] = {0,  1,  28, 2,  29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4,  8,
                                      31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6,  11, 5,  10, 9};
    return table[((bit & -bit) * 0x077CB531) >> 27];
  }
  int block_query(const int l, const int r, const int bl_n) const {
    int bl_l = bl_size * bl_n, x = bit[r] & ~((1 << (l - bl_l)) - 1);
    return x ? bl_l + lsb(x) : r;
  }

  public:
  RangeMinmaxQuery(void) {}
  RangeMinmaxQuery(const vector<T> &v) { init(v); }
  void init(const vector<T> &v) {
    origin = v, v_size = v.size(), bl_size = 0;
    while ((1 << bl_size) < v_size) ++bl_size;
    bl_size = max(1, bl_size >> 1);
    bl_num  = (v_size + bl_size - 1) / bl_size;
    vector<pair<T, int>> bl_v(bl_num, {numeric_limits<T>::max(), INT_MAX});
    for (int i = 0, j = 0; i < v_size; ++i, j = i / bl_size) if (comp(v[i], bl_v[j].first)) bl_v[j] = {v[i], i};
    st.init(move(bl_v));
    bit.assign(v_size, 0);
    for (int i = 0, l = 0; i < bl_num; ++i, l += bl_size) {
      vector<int> helper(bl_size), inc(bl_size);
      for (int j = 0, now = -1, r = min(bl_size, v_size - l); j < r; ++j) {
        while (now >= 0 && !comp(v[l + inc[now]], v[l + j])) --now;
        helper[j]  = now >= 0 ? inc[now] : -1;
        inc[++now] = j;
      }
      for (int j = 0, r = min(bl_size, v_size - l); j < r; ++j) bit[l + j] = helper[j] >= 0 ? bit[l + helper[j]] | (1 << helper[j]) : 0;
    }
  }
  T   query(const int l, const int r) const { return origin[query_index(l, r)]; }
  int query_index(int l, int r) const {
    int lbl_n = l / bl_size, rbl_n = --r / bl_size, lbl_p = l % bl_size, rbl_p = r % bl_size;
    if (lbl_n == rbl_n) return block_query(l, r, lbl_n);
    int lret = lbl_p > 0 ? block_query(l, l - lbl_p + bl_size - 1, lbl_n++) : l;
    int rlet = rbl_p < bl_size - 1 ? block_query(r - rbl_p, r, rbl_n--) : r;
    int ret  = comp(origin[rlet], origin[lret]) ? rlet : lret;
    if (lbl_n <= rbl_n) {
      pair<T, int> mret = st.query(lbl_n, rbl_n + 1);
      if (comp(mret.first, origin[ret])) ret = mret.second;
    }
    return ret;
  }
  int size(void) const { return v_size; }
};

void scan(int &d) {
  d = 0;
  int c;
  while (c = fgetc(stdin), c == ' ' || c == '\n');
  do d = d * 10 + c - '0';
  while (c = fgetc(stdin), c != ' ' && c != '\n');
}

int read() {
  int d;
  scan(d);
  return d;
}

int main(void) {
  int n = read(), l = read();
  vector<int> a(n);
  rep (i, n) a[i] = read();

  RangeMinmaxQuery<int> rmq(move(a));
  for (int i = 0, r = n - l; i <= r; ++i) printf("%d%c", rmq.query(i, i + l), i == r ? '\n' : ' ');
  return 0;
}


Measured memory_bytes: 29756