Problem:
Score : 600 points

Problem Statement

You are given an integer sequence A of length N and an integer K.
You will perform the following operation on this sequence Q times:

Choose a contiguous subsequence of length K, then remove the smallest element among the K elements contained in the chosen subsequence (if there are multiple such elements, choose one of them as you like).

Let X and Y be the values of the largest and smallest element removed in the Q operations. You would like X-Y to be as small as possible.
Find the smallest possible value of X-Y when the Q operations are performed optimally.

Constraints

1 \leq N \leq 2000

1 \leq K \leq N

1 \leq Q \leq N-K+1

1 \leq A_i \leq 10^9

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N K Q
A_1 A_2 ... A_N

Output

Print the smallest possible value of X-Y.

Sample Input 1

5 3 2
4 3 1 5 2

Sample Output 1

1

In the first operation, whichever contiguous subsequence of length 3 we choose, the minimum element in it is 1.
Thus, the first operation removes A_3=1 and now we have A=(4,3,5,2).
In the second operation, it is optimal to choose (A_2,A_3,A_4)=(3,5,2) as the contiguous subsequence of length 3 and remove A_4=2.
In this case, the largest element removed is 2, and the smallest is 1, so their difference is 2-1=1.

Sample Input 2

10 1 6
1 1 2 3 5 8 13 21 34 55

Sample Output 2

7

Sample Input 3

11 7 5
24979445 861648772 623690081 433933447 476190629 262703497 211047202 971407775 628894325 731963982 822804784

Sample Output 3

451211184

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <iostream>
#include <iomanip>
#include <vector>
#include <valarray>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <stack>
#include <bitset>
#include <utility>
#include <numeric>
#include <algorithm>
#include <functional>
#include <complex>
#include <string>
#include <sstream>

#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cassert>

#include <unordered_set>
#include <unordered_map>
#include <random>
#include <thread>
#include <chrono>

using namespace std;

#define all(c) c.begin(), c.end()
#define repeat(i, n) for (int i = 0; i < static_cast<int>(n); i++)
#define debug(x) #x << "=" << (x)

#ifdef DEBUG
#define dump(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define dump(x) 
#endif

typedef complex<double> point;

template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v)
{
    os << "{";
    for(auto it = v.begin(); it != v.end(); ++it) {
        if(it != v.begin())
            os << ",";
        os << *it;
    }
    return os << "}";
}

using ll = int64_t;

struct SegmentTree{
    // // edit this things! Range Sum Query
    // static const int INIT_VALUE = 0;
    // inline int calc(int a,int b){
    //     return a+b;
    // }

    // Range Minimum Query
    static const int INIT_VALUE = 1 << 30;
    inline int calc(int a,int b){
        return min(a,b);
    }

    vector<int> data;
    int n;
    explicit SegmentTree(int _n){
        n = 1;
        while(n < _n) n *= 2;
        data = vector<int>(2*n-1,INIT_VALUE);
    }

    void update(int i,int v){
        int k = i + n-1;
        data[k] = v;
        while(k > 0){
            k = parent(k);
            data[k] = calc(data[get_left(k)],data[get_right(k)]);
        }
    }

    // return data of [a,b).
    inline int get(int a,int b){
        return get(a,b,0,0,n);
    }
private:
    // l,r is segment of node k.
    int get(int a,int b,int k,int l,int r){
        if(r <= a or b <= l) return INIT_VALUE;
        if(a <= l and r <= b) return data[k];
        int vl = get(a,b,get_left(k),l,(l+r)/2);
        int vr = get(a,b,get_right(k),(l+r)/2,r);
        return calc(vl,vr);
    }

    inline int get_left(int x){
        return 2*x+1;
    }
    inline int get_right(int x){
        return 2*x+2;
    }
    inline int parent(int x){
        return (x-1)/2;
    }
};

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

    int n, k, q;
    cin >> n >> k >> q;
    vector<int> a(n);
    SegmentTree tree(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        tree.update(i, a[i]);
    }
    if(q == 1) {
        cout << 0 << endl;
        return 0;
    }

    int ret = 1000000001;
    for (int p = 0; p < n; p++) {
        dump(p);
        vector<int> c = a;
        // assume k is small one
        bool ok = false;
        for (int left = max(0, p - k + 1); left <= p; left++){
            int right = left + k - 1;
            if (right >= n)
                break;
            ok = ok || tree.get(left, right + 1) == a[p];
        }
        if(!ok)
            continue;

        c.erase(c.begin() + p, c.begin() + p + 1);
        dump(c);
        vector<pair<int, int>> ds;
        int left = 0;
        int n = c.size();
        while (left < n) {
            while(left < n && c[left] < a[p]) {
                left++;
            }
            int right = left;
            while(right < n && c[right] >= a[p]) {
                right++;
            }
            if (right == n)
                right--;
            if (right - left + 1 >= k) {
                ds.push_back({ left, right });
            }
            left = right + 1;
        }
        std::vector<int> vv;
        for (auto p : ds) {
            sort(c.begin() + p.first, c.begin() + p.second + 1);

            for (int i = 0; i < p.second - p.first + 1 - k + 1; i++){
                vv.push_back(c[p.first + i]);
            }
        }
        dump(vv);
        if (vv.size() < q-1)
            continue;
        dump(c);
        dump(vv);
        sort(all(vv));
        int m = vv[q - 2];
        ret = min(ret, m - a[p]);
    }
    cout << ret << endl;
    return 0;
}