#define NDEBUG
#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 <typename 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 constexpr size_type z = ~static_cast<size_type>(1);
		bool normalize(const size_type x, const size_type y) {
			if (!comp(c[y], c[x]))
				return false;
			std::swap(c[x], c[y]);
			return true;
		}
		void build() {
			const size_type s = size() + 1;
			if (s & 1) {
				normalize(s & z, s);
				buildmin(s >> 1);
				buildmax(s >> 1);
				return;
			}
			if (s == 2)
				return;
			if (normalize(s, s >> 1 | 1))
				buildmax(s >> 2);
			buildmin(s >> 1);
		}
		void buildmin(size_type i) {
			while (i > 1 && normalize(i & z, i << 1))
				i >>= 1;
		}
		void buildmax(size_type i) {
			while (i > 1 && normalize(i << 1 | 1, i | 1))
				i >>= 1;
		}

	public:
		explicit IntervalHeap(const value_compare &x = value_compare())
			: c(2), comp(x) {}
		bool empty() const { return c.size() == 2; }
		size_type size() const { return c.size() - 2; }
		const_reference min() const {
			assert(!empty());
			return c[2];
		}
		const_reference max() const {
			assert(!empty());
			return size() == 1 ? c[2] : c[3];
		}
		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());
			const size_type s = size() + 1;
			std::swap(c[2], c[s]);
			c.pop_back();
			size_type i = 4;
			while (i < s) {
				if ((i | 2) < s && !comp(c[i], c[i | 2]))
					i |= 2;
				if (!normalize(i >> 1 & z, i))
					return;
				if ((i | 1) < s)
					normalize(i, i | 1);
				i <<= 1;
			}
		}
		void pop_max() {
			assert(!empty());
			const size_type s = size() + 1;
			if (s == 2)
				return pop_min();
			std::swap(c[3], c[s]);
			c.pop_back();
			size_type i = 5;
			while (i < s) {
				if ((i | 2) < s && !comp(c[i | 2], c[i]))
					i |= 2;
				if (!normalize(i, i >> 1 | 1))
					return;
				normalize(i & z, i);
				i = (i & z) << 1 | 1;
			}
		}
};

#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <functional>
#include <utility>

template <typename T, class Compare = std::greater<T>> class PairingHeap {
	static constexpr std::uint_fast64_t ALLOCSIZE = (std::uint_fast64_t)1 << 10;

public:
	using value_type = T;
	using reference = value_type &;
	using const_reference = const value_type &;
	using size_type = std::uint_fast32_t;

private:
	struct node_t {
		value_type data;
		node_t *left, *right;
	};
	node_t *root;
	size_type size_;
	static node_t *merge(node_t *x, node_t *y) {
		static const Compare comp = Compare();
		if (comp(y->data, x->data))
			std::swap(x, y);
		x->right = y->left;
		y->left = x;
		return y;
	}

public:
	PairingHeap() : root(nullptr), size_(0) {}
	const_reference top() const {
		assert(root);
		return root->data;
	}
	const_reference pop() {
		assert(root);
		--size_;
		const_reference ret = root->data;
		node_t *n = nullptr, *x = root->left, *y;
		while (x) {
			y = x;
			if (x->right) {
				x = x->right->right;
				y = merge(y, y->right);
			}
			else
				x = nullptr;
			y->right = n;
			n = y;
		}
		if (!n) {
			root = nullptr;
			return ret;
		}
		root = n;
		n = n->right;
		while (n) {
			x = n;
			n = n->right;
			root = merge(root, x);
		}
		return ret;
	}
	void push(const_reference data) {
		static node_t *pool = nullptr;
		static std::uint_fast64_t it = ALLOCSIZE;
		if (it == ALLOCSIZE) {
			pool = (node_t *)malloc(ALLOCSIZE * sizeof(node_t));
			it = 0;
		}
		node_t *top = &pool[it++];
		top->data = data;
		top->left = nullptr;
		root = root ? merge(root, top) : top;
		++size_;
	}
	bool empty() const { return !root; }
	size_type size() const { return size_; }
	void meld(PairingHeap<T, Compare> &other) {
		size_ += other.size_;
		other.size_ = 0;
		if (other.root) {
			root = root ? merge(root, other.root) : other.root;
			other.root = nullptr;
		}
	}
};

#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<PairingHeap<int>> heaps(n);
	int ans = ::std::numeric_limits<int>::max();
	for (int i = 0;i < n;++i)
		heaps[i].push(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].meld(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