Рухомі точки#230

Рухомі точки (Розбір)

Спершу з'ясуємо, скільки коштує одне злиття. Щоб об'єднати дві сусідні крапки, які стоять на відстані , достатньо рухати одну з них назустріч іншій — це рівно секунд. Кожне таке злиття зменшує кількість крапок на одиницю.

Тепер ключове спостереження: злиття різних пар незалежні. Відсортуємо крапки й позначимо проміжки між сусідніми через d_1, d_2, \ldots, d_{n-1}. Щоб «схлопнути» групу підряд розташованих крапок, треба витратити суму всіх проміжків усередині цієї групи. Тому будь-який план зводиться до вибору підмножини проміжків, які ми закриваємо; вартість — сума обраних проміжків, а виграш — по одній крапці за кожен.

Отже, щоб за час прибрати якнайбільше крапок, вигідно закривати найменші проміжки.

Звідси алгоритм:

  1. відсортувати координати й прибрати дублікати — крапки, що вже збіглися, злиті задарма;

  2. порахувати проміжки між сусідніми різними координатами;

  3. відсортувати проміжки за зростанням і побудувати їхні префіксні суми;

  4. на запит двійковим пошуком знайти найбільше з d_1 + \ldots + d_j \le t; відповідь — (\text{кількість різних крапок}) - j.

Складність — \mathcal{O}(n \log n + q \log n).

Не забудьте про дублікати у вхідних даних: без попереднього прибирання однакових координат серед проміжків з'являться нулі, і хоч відповідь від цього не зіпсується, початкову кількість крапок треба брати саме після злиття збіжних.