Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Основная идея решения.
- //
- // Упорядочить элементы по возрастанию. Посчитать количество пар,
- // между которыми разность не больше чем, данная. Если количество
- // пар оказалось больше, чем k, то пробуем для меньшей разности,
- // если меньше, чем k, то делаем подсчёт для большей разности.
- // Используем двоичный поиск при этом.
- //
- // Подсчёт пар для заданной разности d основан на положении,
- // что если разность между крайними числами в промежутке равна d,
- // то и все пары в промежутке дают разность не превосходящую d.
- import java.io.*;
- import java.util.*;
- import java.util.stream.*;
- public class Main {
- // Функция выдаёт количество различных пар, которые
- // могут дать d элементов.
- static int countDiffs(int d) {
- return (int)(d * (d - 1) * 0.5);
- }
- // Функция выдаёт количество пар в листе a,
- // дающих разности, не превосходящих целевую разность d.
- static int countListDiffs(int[] a, int d) {
- int count, l, r, r_prev;
- count = l = r = r_prev = 0;
- while (r < a.length) {
- // Находим стартовую (левую) позицию для следующего полуинтервала,
- // включающего пары, с разностью, не превышающей d.
- // В первой итерации внешнего цикла ни одна итерация этого
- // внутреннего цикла выполнена не будет.
- while (a[r] - a[l] > d && l < r) {
- l += 1;
- }
- // Сдвигаем правую границу до тех пор, пока полуинтервал
- // [l; r) не будет включать максимально возможное количество
- // пар, с разностью, не превосходящей d.
- while (r < a.length && a[r] - a[l] <= d) {
- r += 1;
- }
- // Любая из пар на полуинтервале [l; r) даёт разность,
- // не превосходящую d.
- count += countDiffs(r - l);
- if (r_prev - l > 1) {
- // Если полуинтервал пересекается с предыдущим, то пары из
- // пересечения-полуинтервала [l; r_prev) учитываются
- // дважды при суммировании количеств. Необходимо вычесть
- // количество, которое даёт пересечение.
- count -= countDiffs(r_prev - l);
- }
- // Сохраняем предыдущее значение r, чтобы потом учесть
- // возможное пересечение полуинтервалов.
- r_prev = r;
- }
- return count;
- }
- // Найти k-ю по величине разницу между элементами a.
- static int getKth(int[] a, int k) {
- Arrays.sort(a);
- int lo = 0, hi = a[a.length-1], mid;
- while (hi > lo) {
- mid = (hi + lo) / 2;
- if (countListDiffs(a, mid) < k) {
- // Если количество пар для разности mid меньше k,
- // то искомая разность будет больше mid и,
- // следовательно, нижняя граница lo будет больше mid.
- lo = mid + 1;
- } else {
- hi = mid;
- }
- }
- return lo;
- }
- public static void main(String[] args) throws IOException {
- BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
- reader.readLine();
- String[] tokens = reader.readLine().split(" ");
- int[] a = Stream.of(tokens)
- .mapToInt(token -> Integer.parseInt(token))
- .toArray();
- int k = Integer.parseInt(reader.readLine());
- int result = getKth(a, k);
- System.out.println(result);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement