#define NDEBUG
#include <cassert>
#include <iterator>
#include <utility>
#include <vector>


template <class Monoid, template <class> class Container> class segment_tree {
public:
	using value_structure = Monoid;
	using value_type = typename value_structure::value_type;
	using container_type = Container<value_type>;
	using const_reference = typename container_type::const_reference;
	using size_type = typename container_type::size_type;

private:
	size_type size_;
	container_type tree;
	static size_type getsize(const size_type size) {
		size_type ret = 1;
		while (ret < size)
			ret <<= 1;
		return ret;
	}
	void recalc(const size_type index) {
		tree[index] =
			value_structure::operation(tree[index << 1], tree[index << 1 | 1]);
	}
	size_type base_size() const { return tree.size() >> 1; }

public:
	segment_tree() : size_(0), tree() {}
	explicit segment_tree(const size_type size)
		: size_(size), tree(getsize(size) << 1, value_structure::identity()) {}
	template <class InputIterator>
	segment_tree(InputIterator first, InputIterator last)
		: size_(::std::distance(first, last)), tree() {
		const size_type cap = getsize(size_);
		tree.reserve(cap << 1);
		tree.resize(cap, value_structure::identity());
		tree.insert(tree.end(), first, last);
		tree.resize(cap << 1, value_structure::identity());
		for (size_type i = cap - 1; i; --i)
			recalc(i);
	}

	bool empty() const { return !size_; }
	size_type size() const { return size_; }

	const_reference operator[](const size_type index) const {
		assert(index < size());
		return tree[index + base_size()];
	}
	value_type fold(size_type first, size_type last) const {
		assert(first <= last);
		assert(last <= size());

		value_type ret_l = value_structure::identity(),
			ret_r = value_structure::identity();
		for (first += base_size(), last += base_size(); first < last;
			first >>= 1, last >>= 1) {
			if (first & 1)
				ret_l = value_structure::operation(ret_l, tree[first++]);
			if (last & 1)
				ret_r = value_structure::operation(tree[last - 1], ret_r);
		}
		return value_structure::operation(ret_l, ret_r);
	}
	template <class F> size_type search(const F &f) const {
		if (f(value_structure::identity()))
			return 0;
		if (!f(tree[1]))
			return size() + 1;
		value_type acc = value_structure::identity();
		size_type i = 1;
		while (i < base_size())
			if (!f(value_structure::operation(acc, tree[i <<= 1])))
				acc = value_structure::operation(acc, tree[i++]);
		return i - base_size() + 1;
	}

	template <class F> void update(size_type index, const F &f) {
		assert(index < size());
		index += base_size();
		tree[index] = f(tree[index]);
		while (index >>= 1)
			recalc(index);
	}
	void set(size_type index, const value_type &value) {
		assert(index < size());
		index += base_size();
		tree[index] = value;
		while (index >>= 1)
			recalc(index);
	}
	void set(size_type index, value_type &&value) {
		assert(index < size());
		index += base_size();
		tree[index] = ::std::move(value);
		while (index >>= 1)
			recalc(index);
	}
};

#include <algorithm>
#include <limits>
template <class T> class min_monoid {
public:
	using value_type = T;
	static value_type operation(const value_type &x, const value_type &y) {
		return ::std::min(x, y);
	}
	static value_type identity() {
		return ::std::numeric_limits<value_type>::max();
	}
	static value_type reverse(const value_type &x) { return x; }
};

#include<cstdio>
#include<vector>
using uint = unsigned int;
template<class T>
using vec_alias = ::std::vector<T>;

void scan(uint &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');
}

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

int main() {
	const uint n = read(), l = read();
	::std::vector<uint> a(n);
	for (auto &e : a)
		scan(e);
	segment_tree<min_monoid<uint>,vec_alias> seq(a.begin(),a.end());

	for (uint i = 0;i <= n - l;++i)
		printf("%u%c", seq.fold(i, i + l), " \n"[i == n - l]);

	return 0;
}


Measured memory_bytes: 14508