#include <cassert>
#include <cstddef>
#include <numeric>
#include <utility>
#include <vector>

class UnionFind {

public:
	using size_type = std::size_t;
	using container_type = std::vector<size_type>;

protected:
	container_type p, s;

public:
	UnionFind() : p(), s() {}
	explicit UnionFind(const size_type size)
		: p(size), s(size, static_cast<size_type>(1)) {
		std::iota(p.begin(), p.end(), static_cast<size_type>(0));
	}

	size_type size() const { return p.size(); }
	bool empty() const { return p.empty(); }

	size_type find(size_type x) {
		assert(x < size());
		while (p[x] != x)
			x = p[x] = p[p[x]];
		return x;
	}
	bool same(const size_type x, const size_type y) {
		assert(x < size());
		assert(y < size());
		return find(x) == find(y);
	}
	size_type size(const size_type x) {
		assert(x < size());
		return s[find(x)];
	}

	::std::pair<size_type, size_type> unite(size_type x, size_type y) {
		assert(x < size());
		assert(y < size());
		x = find(x);
		y = find(y);
		if (x != y) {
			if (s[x] < s[y])
				std::swap(x, y);
			s[x] += s[y];
			p[y] = x;
		}
		return{ x,y };
	}
};

#include <cassert>
#include <functional>
#include <utility>
#include <vector>

template <class T, class Container = ::std::vector<T>,
	class Compare = ::std::less<typename Container::value_type>>
	class IntervalHeap {

	public:
		using container_type = Container;
		using value_compare = Compare;
		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;

	protected:
		container_type c;
		value_compare comp;

	private:
		static size_type left(const size_type i) { return (i - 1) << 1; }
		static size_type right(const size_type i) { return (i << 1) - 1; }
		bool normalize(const size_type l, const size_type g) {
			if (!comp(c[g], c[l]))
				return false;
			::std::swap(c[l], c[g]);
			return true;
		}
		void build() {
			const size_type s = (size() + 1) >> 1;
			if (!(size() & 1))
				if (normalize(left(s), right(s)))
					buildmin(s);
				else
					buildmax(s);
			else if (size() != 1)
				if (normalize(left(s), right(s >> 1)))
					buildmax(s >> 1);
				else
					buildmin(s);
		}
		void buildmin(size_type i) {
			while (i != 1 && normalize(left(i >> 1), left(i)))
				i >>= 1;
		}
		void buildmax(size_type i) {
			while (i != 1 && normalize(right(i), right(i >> 1)))
				i >>= 1;
		}

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

		bool empty() const { return c.empty(); }
		size_type size() const { return c.size(); }

		const_reference min() const {
			assert(!empty());
			return c[0];
		}
		const_reference max() const {
			assert(!empty());
			return size() == 1 ? c[0] : c[1];
		}

		void push(const value_type &x) {
			c.push_back(x);
			build();
		}
		void push(value_type &&x) {
			c.push_back(::std::move(x));
			build();
		}
		template <class... Args> void emplace(Args &&... args) {
			c.emplace_back(::std::forward<Args>(args)...);
			build();
		}
		void pop_min() {
			assert(!empty());
			::std::swap(c.front(), c.back());
			c.pop_back();
			const size_type s = size();
			size_type i = 2;
			while (left(i) < s) {
				if (left(i | 1) < s && !comp(c[left(i)], c[left(i | 1)]))
					i |= 1;
				if (!normalize(left(i >> 1), left(i)))
					return;
				if (right(i) < s)
					normalize(left(i), right(i));
				i <<= 1;
			}
		}
		void pop_max() {
			assert(!empty());
			if (size() == 1) {
				c.pop_back();
				return;
			}
			::std::swap(c[1], c.back());
			c.pop_back();
			const size_type s = size();
			size_type i = 2;
			while (right(i) < s) {
				if (right(i | 1) < s && !comp(c[right(i | 1)], c[right(i)]))
					i |= 1;
				if (!normalize(right(i), right(i >> 1)))
					return;
				normalize(left(i), right(i));
				i <<= 1;
			}
		}
};

#include <cassert>
#include <cstddef>
#include <functional>
#include <memory>
#include <type_traits>
#include <utility>

template <class T, class Compare = ::std::less_equal<T>> class pairing_heap {

public:
	using value_type = T;
	using const_reference = const value_type &;
	using size_type = ::std::size_t;
	using value_compare = Compare;

private:
	struct node_type {
		value_type value;
		::std::unique_ptr<node_type> left, right;
		template <class... Args>
		node_type(Args &&... args)
			: value(::std::forward<Args>(args)...), left(), right() {}
	};
	using pointer = ::std::unique_ptr<node_type>;
	pointer root;
	value_compare comp;
	size_type s;
	pointer merge(pointer x, pointer y) {
		if (!x)
			return ::std::move(y);
		if (!y)
			return ::std::move(x);
		if (!comp(x->value, y->value))
			x.swap(y);
		y->right = ::std::move(x->left);
		x->left = ::std::move(y);
		return ::std::move(x);
	}
	pointer mergelist(pointer curr) {
		pointer head, temp, next;
		while (curr) {
			next = ::std::move(curr->right);
			if (next) {
				temp = ::std::move(next->right);
				curr = merge(::std::move(curr), ::std::move(next));
			}
			curr->right = ::std::move(head);
			head = ::std::move(curr);
			curr = ::std::move(temp);
		}
		while (head) {
			next = ::std::move(head->right);
			curr = merge(::std::move(curr), ::std::move(head));
			head = ::std::move(next);
		}
		return ::std::move(curr);
	}

public:
	pairing_heap() : root(), comp(), s(0) {}
	explicit pairing_heap(const value_compare &x) : root(), comp(x), s(0) {}

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

	const_reference top() const noexcept {
		assert(!empty());
		return root->value;
	}

	void push(const value_type &x) {
		root = merge(::std::move(root), ::std::make_unique<node_type>(x));
		++s;
	}
	void push(value_type &&x) {
		root = merge(::std::move(root), ::std::make_unique<node_type>(::std::move(x)));
		++s;
	}
	template <class... Args> void emplace(Args &&... args) {
		root = merge(::std::move(root),
			::std::make_unique<node_type>(::std::forward<Args>(args)...));
		++s;
	}

	void pop() {
		assert(!empty());
		root = mergelist(::std::move(root->left));
		--s;
	}

	void meld(pairing_heap &x) {
		s += x.s;
		x.s = 0;
		root = merge(::std::move(root), ::std::move(x.root));
	}
	pairing_heap &operator+=(pairing_heap &x) {
		meld(x);
		return *this;
	}
};

#include <algorithm>
#include <iostream>
#include <limits>
#include <numeric>
#include <tuple>
#include <vector>

int main() {
	int n, k, q;
	::std::cin >> n >> k >> q;
	::std::vector<int> a(n), b(n);
	for (auto &e : a)
		::std::cin >> e;
	::std::iota(b.begin(), b.end(), 0);
	::std::sort(b.begin(), b.end(), [&](int x, int y) {return a[x] > a[y];});

	::std::vector<char> used(n, 0);
	UnionFind T(n);
	IntervalHeap<int> H;
	::std::vector<pairing_heap<int>> heaps(n);
	int ans = ::std::numeric_limits<int>::max();
	for (int i = 0;i < n;++i)
		heaps[i].emplace(a[i]);
	for (const auto i : b) {
		used[i] = 1;
		if (i != 0 && used[i - 1]) {
			int x, y;
			::std::tie(x, y) = T.unite(i, i - 1);
			heaps[x].meld(heaps[y]);
		}
		if (i != n - 1 && used[i + 1]) {
			int x, y;
			::std::tie(x, y) = T.unite(i, i + 1);
			heaps[x]+=heaps[y];
		}
		auto &t = heaps[T.find(i)];
		while (t.size() >= k) {
			H.emplace(t.top());
			t.pop();
		}
		if (H.size() >= q) {
			while (H.size() > q)
				H.pop_max();
			ans = ::std::min(ans, H.max() - H.min());
		}
	}

	::std::cout << ans << ::std::endl;

	return 0;
}


Measured memory_bytes: 384