//#define NDEBUG
#define _CRT_SECURE_NO_WARNINGS
#include <array>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <limits>
#include <memory>
#include <string>
#include <type_traits>

template <class Integral> class Rirange;

template <class Integral = std::size_t> class irange {
public:
	using value_type = Integral;
	using reference = value_type &;
	using const_reference = const value_type &;
	class irangeitr {
		friend irange;
		value_type i;
		irangeitr(const value_type x) noexcept : i(x) {}

	public:
		void operator++() noexcept { ++i; }
		value_type &operator*() noexcept { return i; }
		const_reference operator*() const noexcept { return i; }
		bool operator!=(const irangeitr &x) const noexcept { return i < x.i; }
	};

private:
	const value_type f, l;

public:
	irange(const value_type first, const value_type last) noexcept
		: f(first), l(last) {}
	irangeitr begin() const noexcept { return irangeitr(f); }
	irangeitr end() const noexcept { return irangeitr(l); }
	Rirange<value_type> rev() const noexcept {
		return Rirange<value_type>(l - 1, f - 1);
	}
};
template <class Integral = std::size_t> class Rirange {
public:
	using value_type = Integral;
	using reference = value_type &;
	using const_reference = const value_type &;
	class Rirangeitr {
		friend Rirange;
		value_type i;
		Rirangeitr(const value_type x) noexcept : i(x) {}

	public:
		void operator++() noexcept { --i; }
		reference operator*() noexcept { return i; }
		const_reference operator*() const noexcept { return i; }
		bool operator!=(const Rirangeitr &x) const noexcept {
			return (!~x.i && ~i) || x.i < i;
		}
	};

private:
	const value_type f, l;

public:
	Rirange(const value_type x, const value_type y) noexcept : f(x), l(y) {}
	Rirangeitr begin() const noexcept { return Rirangeitr(f); }
	Rirangeitr end() const noexcept { return Rirangeitr(l); }
	irange<value_type> rev() const noexcept {
		return irange<value_type>(l + 1, f + 1);
	}
};

template <class T> bool maxi(T &a, const T &b) {
	if (b < a)
		return 0;
	a = b;
	return 1;
}
template <class T> bool mini(T &a, const T &b) {
	if (a < b)
		return 0;
	a = b;
	return 1;
}
template <class T> bool smaxi(T &a, const T &b) {
	if (a < b) {
		a = b;
		return 1;
	}
	return 0;
}
template <class T> bool smini(T &a, const T &b) {
	if (b < a) {
		a = b;
		return 1;
	}
	return 0;
}
struct customIO {
	int c;
	bool f;
	std::array<int, 30> buf;
	const std::array<int, 10> itoc;
	std::array<std::uint_least8_t, 256> ctoi_base;
	const std::uint_least8_t *const ctoi;
	void get_c() { c = fgetc(stdin); }
	void put_c(int x) { fputc(x, stdout); }
	bool vacant() { return c == ' ' || c == '\n'; }
	operator int() { return 0; }

	explicit customIO()
		: itoc({ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }),
		ctoi(std::addressof(ctoi_base[-static_cast<std::int_fast16_t>(
			std::numeric_limits<char>::min())])) {
		for (std::uint_least8_t i = 0; i < 10; ++i)
			ctoi_base[static_cast<int>("0123456789"[i]) -
			static_cast<std::int_fast16_t>(
				std::numeric_limits<char>::min())] = i;
	}
	// in

	void cueing() {
		while (get_c(), vacant())
			;
	}
	template <class T>
	auto operator>>(T &d) ->
		typename std::enable_if<std::is_signed<T>::value, customIO &>::type {
		d = 0;
		f = 0;
		cueing();
		if (c == '-')
			f = 1, get_c();
		do
			d = d * 10 + ctoi[c];
		while (get_c(), !vacant());
		if (f)
			d = -d;
		return *this;
	}
	template <class T>
	auto operator>>(T &d) ->
		typename std::enable_if<!std::is_signed<T>::value, customIO &>::type {
		d = 0;
		cueing();
		do
			d = d * 10 + ctoi[c];
		while (get_c(), !vacant());
		return *this;
	}
	customIO &operator>>(char &d) {
		cueing();
		d = c;
		return *this;
	}
	customIO &operator>>(double &d) {
		scanf("%lf", &d);
		return *this;
	}
	customIO &operator>>(std::string &d) {
		d.clear();
		cueing();
		do
			d.push_back(c);
		while (get_c(), !vacant());
		return *this;
	}
	template <class T> T input() {
		T d;
		*this >> d;
		return d;
	}

	// out

	template <class T>
	auto operator<<(T d) ->
		typename std::enable_if<std::is_signed<T>::value, customIO &>::type {
		c = 0;
		f = 0;
		if (d < static_cast<T>(0))
			f = 1, d = -d;
		while (d)
			buf[c++] = itoc[d % 10], d /= 10;
		if (!c)
			buf[c++] = itoc[0];
		if (f)
			put_c('-');
		while (c--)
			put_c(buf[c]);
		return *this;
	}
	template <class T>
	auto operator<<(T d) ->
		typename std::enable_if<!std::is_signed<T>::value, customIO &>::type {
		c = 0;
		while (d)
			buf[c++] = itoc[d % 10], d /= 10;
		if (!c)
			buf[c++] = itoc[0];
		while (c--)
			put_c(buf[c]);
		return *this;
	}
	customIO &operator<<(char d) {
		put_c(d);
		return *this;
	}
	customIO &operator<<(double d) {
		printf("%f", d);
		return *this;
	}
	customIO &operator<<(const std::string &d) {
		for (const auto e : d)
			put_c(e);
		return *this;
	}
	customIO &operator<<(const char *d) {
		while (*d != '\0')
			put_c(*(d++));
		return *this;
	}
	void endl() { put_c('\n'); }
	void space() { put_c(' '); }
} IO;

using int32 = std::int_fast32_t;
using int64 = std::int_fast64_t;
using uint32 = std::uint_fast32_t;
using uint64 = std::uint_fast64_t;
using intl32 = std::int_least32_t;
using intl64 = std::int_least64_t;
using uintl32 = std::uint_least32_t;
using uintl64 = std::uint_least64_t;
#include <cassert>
#include <cstddef>
#include <functional>
#include <utility>

template <class T, template <class> class Container,
	class Compare = std::less<T>>
	class SlidingMinimum {

	public:
		using value_type = T;
		using size_type = std::size_t;
		using const_reference = const value_type &;
		using value_compare = Compare;
		using element_type = std::pair<value_type, size_type>;
		using container_type = Container<element_type>;

	protected:
		container_type c;
		value_compare comp;
		size_type size_;

	public:
		SlidingMinimum() : c(), comp(), size_(0) {}
		explicit SlidingMinimum(const value_compare &x) : c(), comp(x), size_(0) {}
		explicit SlidingMinimum(const value_compare &x, const container_type &other)
			: c(other), comp(x), size_(0) {}
		explicit SlidingMinimum(const value_compare &x, container_type &&other)
			: c(std::move(other)), comp(x), size_(0) {}

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

		const_reference top() const {
			assert(!empty());
			return c.front().first;
		}

		void push(const value_type &x) {
			++size_;
			size_type s = 1;
			while (!c.empty() && comp(x, c.back().first)) {
				s += c.back().second;
				c.pop_back();
			}
			c.emplace_back(x, std::move(s));
		}
		void push(value_type &&x) {
			++size_;
			size_type s = 1;
			while (!c.empty() && comp(x, c.back().first)) {
				s += c.back().second;
				c.pop_back();
			}
			c.emplace_back(std::move(x), std::move(s));
		}
		void pop() {
			assert(!empty());
			if (!(--c.front().second))
				c.pop_front();
		}
		void clear() {
			size_ = 0;
			c.clear();
		}
};

#include <array>
#include <cstddef>
#include <memory>
#include <utility>

template <class T, std::size_t N, template <class> class Allocator>
class ArrayDeque {
	static constexpr std::size_t get_size(const std::size_t acc,
		const std::size_t siz) {
		return acc > siz ? acc : get_size(acc << 1, siz);
	}
	static constexpr std::size_t SIZE = get_size(1, N);
	static constexpr std::size_t MASK = SIZE - 1;

public:
	using container_type = std::array<T, SIZE>;
	using allocator_type = Allocator<T>;
	using value_type = typename container_type::value_type;

	using reference = typename container_type::reference;
	using const_reference = typename container_type::const_reference;
	using size_type = typename container_type::size_type;

private:
	using traits = std::allocator_traits<allocator_type>;

	container_type c;
	allocator_type alc;
	size_type left, right;

public:
	ArrayDeque(const allocator_type &x = allocator_type())
		: c(), alc(x), left(0), right(SIZE - 1) {}
	size_type size() const noexcept { return MASK & (right + 1 - left); }
	size_type max_size() const noexcept { return SIZE - 1; }
	bool empty() const noexcept { return !size(); }

	reference operator[](const size_type i) { return c[(left + i) & MASK]; }
	const_reference operator[](const size_type i) const {
		return c[(left + i) & MASK];
	}
	reference front() { return c[left]; }
	const_reference front() const { return c[left]; }
	reference back() { return c[right]; }
	const_reference back() const { return c[right]; }

	void push_front(const value_type &v) {
		left = (left - 1) & MASK;
		traits::construct(alc, std::addressof(c[left]), v);
	}
	void push_front(value_type &&v) {
		left = (left - 1) & MASK;
		traits::construct(alc, std::addressof(c[left]), std::move(v));
	}
	void push_back(const value_type &v) {
		right = (right + 1) & MASK;
		traits::construct(alc, std::addressof(c[right]), v);
	}
	void push_back(value_type &&v) {
		right = (right + 1) & MASK;
		traits::construct(alc, std::addressof(c[right]), std::move(v));
	}
	template <class... Args> void emplace_front(Args &&... args) {
		left = (left - 1) & MASK;
		traits::construct(alc, std::addressof(c[left]),
			std::forward<Args>(args)...);
	}
	template <class... Args> void emplace_back(Args &&... args) {
		right = (right + 1) & MASK;
		traits::construct(alc, std::addressof(c[right]),
			std::forward<Args>(args)...);
	}
	void pop_front() {
		traits::destroy(alc, std::addressof(c[left]));
		left = (left + 1) & MASK;
	}
	void pop_back() {
		traits::destroy(alc, std::addressof(c[right]));
		right = (right - 1) & MASK;
	}
};



template<class T>
using type = ArrayDeque<T,100000, std::allocator>;

using SL = SlidingMinimum<uint32, type>;

int main() {
	uint32 n, l;
	IO >> n >> l;
	n -= l;

	SL s;

	uint32 a;
	while(l--) {
		IO >> a;
		s.push(a);
	}
	IO << s.top();
	while (n--) {
		IO >> a;
		s.pop();
		s.push(a);
		IO << ' ' << s.top();
	}
	IO.endl();

	return 0;
}


Measured memory_bytes: 4680