// algo.cpp: 定义应用程序的入口点。
//
#include <iostream>
#include <fstream>
#include <ctime>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>
#include <queue>
#include <climits>
#include <cassert>
using namespace std;
struct UnionFind {
    vector<int> par, sz;
    int n_tree;

    explicit UnionFind(int n) : par(n), sz(n, 1), n_tree(n) { //0-indexed
        iota(par.begin(), par.end(), 0);
    }

    int n_cluster() const {
        return n_tree;
    }

    int size(int x) {
        return sz[root(x)];
    }

    int root(int x) {
        return x == par[x] ? x : par[x] = root(par[x]);
    }

    bool unite(int x, int y) {
        int rx = root(x), ry = root(y);
        if (rx != ry) {
            par[rx] = ry;
            --n_tree;
            sz[ry] += sz[rx];
            return true;
        }
        return false;
    }
    bool same(int x, int y) {
        return root(x) == root(y);
    }
    bool is_root(int x) const {
        return par[x] == x;
    }
};
int main()
{
#ifdef LOCAL
    // 如何使用相对路径？
    ifstream in("in.txt");
    cin.rdbuf(in.rdbuf());
#endif
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, k, q;
    cin >> n >> k >> q;
    vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    vector<int> b(n);
    iota(b.begin(), b.end(), 0);
    sort(b.begin(), b.end(), [&](int x, int y) {return a[x] > a[y]; });
    UnionFind uf(n);
    priority_queue<int> global_que;
    vector<priority_queue<int, vector<int>, greater<>>> que(n);
    for (int i = 0; i < n; ++i) {
        que[i].push(a[i]);
    }
    //TODO: 改成可并堆
    //注意：堆合并的顺序要和UnionFind::unite的顺序一致
    auto merge_heap = [&](int j, int i) {
        i = uf.root(i), j = uf.root(j);
        assert(i != j);
        if (que[i].size() < que[j].size()) {
            swap(que[i], que[j]);
        }
        while (!que[j].empty()) {
            que[i].push(que[j].top());
            que[j].pop();
        }
    };
    auto enque = [&](int val) {
        if (global_que.size() < q) {
            global_que.push(val);
        }
        else if (global_que.top() > val) {
            global_que.pop();
            global_que.push(val);
        }
    };

    int min_val{};
    int ans = INT_MAX;
    for (int r = 0; r < n;) {
        int l = r++;
        for (; r < n && a[b[r]] == a[b[l]]; ++r);
        for (int i = l; i < r; ++i) {
            int j = b[i];
            if (j - 1 >= 0 && a[j - 1] >= a[j] && !uf.same(j - 1, j)) {
                merge_heap(j - 1, j);
                uf.unite(j - 1, j);
            }
            if (j + 1 < n && a[j + 1] >= a[j] && !uf.same(j, j + 1)) {
                merge_heap(j, j + 1);
                uf.unite(j, j + 1);
            }
            int id = uf.root(j);
            if (que[id].size() >= k) {
                min_val = a[j];
            }
            while (que[id].size() >= k) {
                enque(que[id].top());
                que[id].pop();
            }
        }
        if (global_que.size() >= q) {
            ans = min(ans, global_que.top() - min_val);
        }
    }
    cout << ans << '\n';
#if defined LOCAL
    cout << "Time elapsed: " << (double)clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}


Measured memory_bytes: 512