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 Rust (1.15.1) (judge verdict: Wrong Answer)

#![allow(unused_imports)]
#![allow(non_snake_case)]

use procon::*;
use std::cmp::{max, min};
use std::collections::*;
use std::ops::*;
use std::*;

fn min_heap() -> BinaryHeap<i64> {
    BinaryHeap::new()
}

fn solve(K: usize, Q: usize, A: Vec<i64>) -> i64 {
    let mut score = std::i64::MAX;

    for y in A.iter().cloned() {
        // Y = y になるケースだけ考える。
        // y 未満の数を含む部分列は選択できない。y 未満の数で数列を切断して各部分を島と呼ぶ。
        // 各島について件のルールで最小値を消していくとき、常に列島の最小値は選択できる。とにかく最小値を消していくことでXを最小化できて、ベスト。

        let mut heap = BinaryHeap::new();
        let mut l = 0;
        for r in 0..(A.len() + 1) {
            if r >= A.len() || A[r] < y {
                let r = (if r >= A.len() { r } else { r + 1 });
                let k = r - l;

                // 長さ K 未満の島からはドロップできないので注意
                if k >= K {
                    for j in l..r {
                        heap.push(-A[j]); // 最大値が出てくるヒープなのでマイナスにしておく
                    }
                }
                l = r + 1;
            }
        }

        println!("y={} {:?}", y, heap.iter().cloned().collect::<Vec<_>>());

        // Q 番目に小さい数を探す
        if heap.len() < Q {
            continue;
        }

        let mut x = None;
        for _ in 0..Q {
            x = heap.pop();
        }

        if let Some(x) = x {
            score = min(score, (-x) - y);
        }

        /*
        let mut islands = Vec::new();
        let mut island = min_heap();
        for a in A.iter().cloned() {
            if a < y {
                if island.len() >= K {
                    islands.push(island);
                    island = min_heap();
                }

            // ignore leading <y s
            } else {
                island.push(-a);
            }
        }

        if island.len() >= K {
            islands.push(island);
        }

        println!("y={} {:?}", y, islands);

        // Q 番目に小さい数を探す
        // 長さ K 未満の島からはドロップできないので注意
        let mut heap = min_heap();

        for mut island in islands {
            let c = island.len() + 1 - K;
            for _ in 0..c {
                heap.push(island.pop().unwrap());
            }
        }

        let mut x = None;
        for _ in 0..Q {
            x = heap.pop();
        }

        if let Some(x) = x {
            score = min(score, (-x) - y);
        }
        */
    }
    score
}

pub fn main() {
    let words = read_words::<usize>();
    let (N, K, Q) = (words[0], words[1], words[2]);
    let A = read_words::<i64>();

    println!("{}", solve(K, Q, A));
    return;
}

pub mod procon {
    use std;
    use std::collections::*;
    use std::io;
    use std::mem;
    use std::str::FromStr;

    pub fn read_line() -> String {
        let mut buf = String::new();
        io::stdin().read_line(&mut buf).unwrap();
        buf.trim_right().to_owned()
    }

    pub fn read_words<T>() -> Vec<T>
    where
        T: std::str::FromStr,
        T::Err: std::fmt::Debug,
    {
        let mut buf = String::new();
        io::stdin().read_line(&mut buf).unwrap();
        buf.split_whitespace()
            .map(|word| T::from_str(word).unwrap())
            .collect()
    }

    pub fn read_vec(len: usize) -> Vec<String> {
        let mut vec = Vec::new();
        while vec.len() < len {
            let line = read_line();
            for word in line.split_whitespace() {
                vec.push(word.to_owned());
            }
        }
        assert!(vec.len() == len);
        vec
    }
}

#[cfg(test)]
pub mod tests {
    use super::*;

    #[test]
    pub fn test_case1() {
        assert_eq!(1, solve(3, 2, vec![4, 3, 1, 5, 2]));
    }

    #[test]
    pub fn test_case2() {
        assert_eq!(7, solve(1, 6, vec![1, 1, 2, 3, 5, 8, 13, 21, 34, 55]));
    }

    #[test]
    pub fn test_case3() {
        assert_eq!(
            451211184,
            solve(
                7,
                5,
                vec![
                    24979445, 861648772, 623690081, 433933447, 476190629, 262703497, 211047202,
                    971407775, 628894325, 731963982, 822804784,
                ]
            )
        );
    }

}