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 (GCC 9.2.1) (judge verdict: Accepted)

#include <stdio.h>

typedef struct {
	int key, id;
} data;

void merge_sort(data x[], int n)
{
	static data y[2001] = {};
	if (n <= 1) return;
	merge_sort(&(x[0]), n/2);
	merge_sort(&(x[n/2]), (n+1)/2);
	
	int i, p, q;
	for (i = 0, p = 0, q = n/2; i < n; i++) {
		if (p >= n/2) y[i] = x[q++];
		else if (q >= n) y[i] = x[p++];
		else y[i] = (x[p].key < x[q].key)? x[p++]: x[q++];
	}
	for (i = 0; i < n; i++) x[i] = y[i];
}

int main()
{
	int i, N, K, Q, A[2001];
	scanf("%d %d %d", &N, &K, &Q);
	for (i = 1; i <= N; i++) scanf("%d", &(A[i]));
	
	data d[2001];
	for (i = 0; i < N; i++) {
		d[i].key = A[i+1];
		d[i].id = i + 1;
	}
	merge_sort(d, N);
	d[N].key = 0;
	
	int j, k, l, r, X, Y, min = 1 << 30, count[2][2001], sum;
	for (i = 0; i < N; i++) {
		if (d[i+1].key == d[i].key) continue;
		Y = d[i].key;
		l = i;
		r = N;
		while (l < r) {
			X = d[(l+r)/2].key;
			for (j = 1, k = 0, count[0][0] = 0, count[1][0] = 0; j <= N; j++) {
				if (A[j] < Y) {
					count[0][++k] = 0;
					count[1][k] = 0;
				} else if (A[j] <= X) count[0][k]++;
				else count[1][k]++;
			}
			for (j = 0, sum = 0; j <= k; j++) {
				if (count[1][j] >= K - 1) sum += count[0][j];
				else if (count[0][j] + count[1][j] >= K) sum += count[0][j] + count[1][j] - K + 1;
			}
			if (sum >= Q) r = (l + r) / 2;
			else l = (l + r) / 2 + 1;
		}
		if (l == N) break;
		else if (d[l].key - Y < min) min = d[l].key - Y;
	}
	
	printf("%d\n", min);
	fflush(stdout);
	return 0;
}