#include <bits/stdc++.h>
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};
  }
};
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;
    }
  }
};
template <class T, class Container = std::vector<T>,
          class Compare = std::less<typename Container::value_type>>
class meld_priority_queue : public std::priority_queue<T, Container, Compare> {
  void cascade_up(const std::size_t i) {
    auto &c = this->c;
    auto &comp = this->comp;
    const std::size_t l = i * 2 + 1;
    const std::size_t r = i * 2 + 2;
    if (r < c.size() && comp(c[l], c[r])) {
      if (comp(c[i], c[r])) {
        std::swap(c[i], c[r]);
      }
    } else {
      if (comp(c[i], c[l])) {
        std::swap(c[i], c[l]);
      }
    }
  }

 public:
  template <class... Args>
  meld_priority_queue(Args &&...args)
      : std::priority_queue<T, Container, Compare>(
            std::forward<Args>(args)...) {}
  void meld(meld_priority_queue &&x) {
    if (x.empty()) {
      return;
    }
    auto &c = this->c;
    std::size_t l = c.size();
    for (T &v : x.c) {
      c.push_back(std::move(v));
    }
    std::size_t r = c.size() - 1;
    while (r != 0) {
      if (l) l = (l - 1) / 2;
      if (r) r = (r - 1) / 2;
      for (std::size_t i = l; i <= r; ++i) {
        cascade_up(i);
      }
    }
  }
};
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<meld_priority_queue<int, std::vector<int>, std::greater<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);
      if (heaps[x].size() < heaps[y].size()) {
        std::swap(heaps[x], heaps[y]);
      }
      heaps[x].meld(std::move(heaps[y]));
    }
    if (i != n - 1 && used[i + 1]) {
      int x, y;
      std::tie(x, y) = T.unite(i, i + 1);
      if (heaps[x].size() < heaps[y].size()) {
        std::swap(heaps[x], heaps[y]);
      }
      heaps[x].meld(std::move(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;
}
