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# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static System.Math;
using MethodImplAttribute = System.Runtime.CompilerServices.MethodImplAttribute;
using MethodImplOptions = System.Runtime.CompilerServices.MethodImplOptions;

public static class P
{
    public static void Main()
    {
        var nkq = Console.ReadLine().Split().Select(int.Parse).ToArray();
        var n = nkq[0];
        var k = nkq[1];
        var q = nkq[2];
        var a = Console.ReadLine().Split().Select(int.Parse).ToArray();
        
        var allSection = new Section() { Start = 0, End = n - 1 };
        Section[] sections = Enumerable.Repeat(allSection, n).ToArray();
        
        var minInd = a.Select((Elem, Ind) => new { Elem, Ind }).OrderBy(x => x.Elem).Select(x => x.Ind).ToArray();
        int ind = 0;
        var min = a[minInd[q - 1]] - a[minInd[0]];
        while (q + ind < n)
        {
            //indを取り除かないとしたら
            var splitAt = minInd[ind];
            var section = sections[splitAt];
            
            var lSection = new Section() { Start = section.Start, End = splitAt - 1 };
            var rSection = new Section() { Start = splitAt + 1, End = section.End };

            sections[splitAt] = null;
            for (int i = lSection.Start; i <= lSection.End; i++)
                sections[i] = lSection;
            for (int i = rSection.Start; i <= rSection.End; i++)
                sections[i] = rSection;

            int[] maxOpeartionCount = new int[n];
            for (int i = 0; i < n; i++)
            {
                var elem = sections[i];
                if (elem == null) continue;
                maxOpeartionCount[elem.Start] = elem.GetOperatableCount(k);
                i = elem.End + 1;
            }

            for (int i = ind + 1; i <= q + ind; i++)
                if (--maxOpeartionCount[sections[minInd[i]].Start] < 0)
                    goto failed;
            
            goto success;
            failed:;
            break;
            success:;
            ind++;
            min = Min(min, a[minInd[q - 1 + ind]] - a[minInd[ind]]);
        }
        Console.WriteLine(min);
    }
}

class Section
{
    public int Start;
    public int End;
    public int Length => End - Start + 1;
    public int GetOperatableCount(int k) => Max(0, Length - k + 1);
}


class SegmentTree<T>
{
    public readonly int Size;
    T Identity;
    Func<T, T, T> Merge;
    int LeafCount;
    int Height;
    T[] Operators;
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public SegmentTree(int size, T identity, Func<T, T, T> merge)
    {
        Size = size;
        Identity = identity;
        Merge = merge;
        Height = 1;
        LeafCount = 1;
        while (LeafCount < size) { Height++; LeafCount <<= 1; }
        Operators = new T[LeafCount << 1];
        for (int i = 0; i < Operators.Length; i++) Operators[i] = identity;
    }

    public T this[int index]
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        get { return Query(index); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        set { Propagate(index += LeafCount); Operators[index] = value; }
    }


    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void Operate(int i, T x) { Propagate(i += LeafCount); Operators[i] = Merge(Operators[i], x); }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void Operate(int l, int r, T x)
    {
        l += LeafCount;
        r += LeafCount;
        Propagate(l);
        Propagate(r);
        while (l <= r)
        {
            if ((l & 1) == 1) Operators[l] = Merge(Operators[l], x);
            if ((r & 1) == 0) Operators[r] = Merge(Operators[r], x);
            l = (l + 1) / 2;
            r = (r - 1) / 2;
        }
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public T Query(int index)
    {
        index += LeafCount;
        Propagate(index);
        return Operators[index];
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private void Propagate(int sectionIndex)
    {
        for (int i = Height - 1; i >= 1; i--)
        {
            var section = sectionIndex >> i;
            var leftChild = sectionIndex >> (i - 1);
            var rightChild = leftChild ^ 1;
            Operators[leftChild] = Merge(Operators[leftChild], Operators[section]);
            Operators[rightChild] = Merge(Operators[rightChild], Operators[section]);
            Operators[section] = Identity;
        }
    }
}