#include <bits/stdc++.h>
using namespace std;

#define rep(i, m, n) for(int(i) = (int)(m); i < (int)(n); ++i)
#define rep2(i, m, n) for(int(i) = (int)(n)-1; i >= (int)(m); --i)
#define REP(i, n) rep(i, 0, n)
#define REP2(i, n) rep2(i, 0, n)
#define all(hoge) (hoge).begin(), (hoge).end()
#define en '\n'
using ll = long long;
using ull = unsigned long long;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
typedef pair<ll, ll> P;
constexpr long long INF = 1LL << 60;
constexpr int INF_INT = 1 << 25;
constexpr long long MOD = (ll)1e9 + 7;
// constexpr long long MOD = 998244353LL;
using ld = long double;
static const ld pi = 3.141592653589793L;
typedef vector<ll> Array;
typedef vector<Array> Matrix;

template <class T> inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T> inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

struct Edge {
    ll to, rev;
    long double cap;
    Edge(ll _to, long double _cap, ll _rev) {
        to = _to;
        cap = _cap;
        rev = _rev;
    }
};
using Edges = vector<Edge>;
using Graph = vector<Edges>;

void add_edge(Graph &G, ll from, ll to, long double cap, bool revFlag,
              long double revCap) {
    G[from].push_back(Edge(to, cap, (ll)G[to].size()));
    if(revFlag)
        G[to].push_back(Edge(from, revCap, (ll)G[from].size() - 1));
}

class UnionFind {
    vector<int> data;
    int num;

  public:
    UnionFind(int size) : data(size, -1), num(size) {}
    bool unionSet(int x, int y) {
        x = root(x);
        y = root(y);
        if(x != y) {
            if(data[y] < data[x]) swap(x, y);
            data[x] += data[y];
            data[y] = x;
            num--;
        }
        return x != y;
    }
    bool findSet(int x, int y) {
        return root(x) == root(y);
    }
    int root(int x) {
        return data[x] < 0 ? x : data[x] = root(data[x]);
    }
    int size(int x) {
        return -data[root(x)];
    }
    int numSet() {
        return num;
    }
};

void solve() {
    ll n, k, q;
    cin >> n >> k >> q;
    vec<ll> a(n);
    REP(i, n) cin >> a[i];
    vec<P> b(n);
    REP(i, n) b[i] = {a[i], i};
    sort(all(b));
    ll ans = b[q-1].first - b[0].first;

    vec<bool> used(n,false);
    multiset<ll> h;//取れるやつ
    vec<multiset<ll>> s(n);
    UnionFind uni(n);

    multiset<ll> nh;

    auto merge_s = [&](int x, int y) {
        x=uni.root(x);y=uni.root(y);
        uni.unionSet(x,y);
        int r=uni.root(x);
        if(r==y) swap(x,y);
        for(auto i:s[y]){
            s[x].insert(i);
        }
        s[y].clear();
        while(s[x].size() >= k){
            auto it=s[x].begin();
            nh.insert(*it);//最小値をhに移動
            s[x].erase(it);
        }
    };

    REP2(i,n){
        int pos=b[i].second;
        s[pos].insert(b[i].first);
        used[pos]=true;

        //マージする
        if(pos > 0 and used[pos - 1]) merge_s(pos - 1, pos);
        if(pos + 1 < n and used[pos + 1]) merge_s(pos + 1, pos);

        //マージすることで使えるようになった要素をためしていく
        while(nh.size()){
            auto it = nh.begin();
            h.insert(*it);
            if(h.size() > q) h.erase(--h.end());//最大値を消去
            if(h.size() == q) chmin(ans, (ll)(*h.rbegin()-*h.begin()));//最大値ー最小値で更新
            nh.erase(it);
        }
    }
    cout<<ans<<en;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    solve();
    // ll t;cin>>t;REP(i,t) solve();

    return 0;
}


Measured memory_bytes: 512