Розбір
Автори задачі: | Матвій Асландуков, Роман Білий та Антон Ципко |
Задачу підготував: | Матвій Асландуков |
Розбір написав: | Матвій Асландуков |
Спочатку необхідно окремо розглянути випадок, коли . У такому випадку ми не можемо зменшити жодне число, а тому якщо є хоча б одне число , то відповідь дорівнює . Інакше усі числа вже спочатку є недодатними, тому можно зробити операцій.
Тепер розглянемо послідовно рішення на кожну групу тестів для :
Блок 1
У першій групі значення , а тому за одну операцію можна просто зменшити будь-яке число . Для того, щоб зробити значення недодатним, необхідно виконати з ним хоча б операцій. А тому мінімальна кількість операцій, за яку можна зробити усі числа недодатними, дорівнує .
Розв'язок: https://pastebin.com/9H9Z2txE
Блок 2
Для розв'язання цієї групи потрібно було визначити критерій того, що можливо зробити усі числа недодатніми рівно за операцій. Для цього спробуємо звести задачу до випадку . А саме, скажемо, що за одну операцію ми збільшуємо усі чисел на , та зменшуємо одне число на . Неважко побачити, що така операція еквівалентна операції з умови. З таким визначенням можна сказать, що після виконання операцій усі збільшаться на . Після цього для того, щоб робити число недодатним, потрібно виконати з ним хоча б операцій. А тому отримуємо доволі простий критерій: усі числа можна зробити недодатними рівно за операцій тоді і тільки тоді, коли .
Маючи цей критерій може здатися, що можна зробити звичайний бінарний пошук по відповіді. Але таке рішення є неправильним, оскільки не завжди існує відповідь, що використовує рівно операцій навіть тоді коли, існує відповідь, що використовує рівно операцій. Наприклад на тесті , можна зробити усі числа недодатними за операції, але не можна за .
Можна довести, що коли відповідь існує, вона не перевищує , де . А тому можна перевірити усі можливі варіанти відповіді від 0 до , використовуючи описаний вище критерій. Для перевірки критерію необхідно зробити операцій, а тому загальна складність такого рішення — .
Розв'язок: https://pastebin.com/E2Q58fqX
Блок 3
Будемо підтримувати поточну відповідь , яка спочатку дорівнює нулю, а також масив , де позначає кількість операцій, зроблених з позицією . На черговій ітерації алгоритму переберемо усі позиції . Якщо для чергової позиції виконується нерівність , необхідно збільшити та на . Якщо на черговій ітерації алгоритму значення не збільшилося, відповідь була знайдена. Якщо ж стало більше ніж , необхідно вивести . Можна довести, що таке рішення працює за . Також можна помітити, що таке рішення зробить рівно одну ітерацію на тестах першої групи і спрацює за .
Розв'язок: https://pastebin.com/f0risSD7
Блок 4
Для початку зрозуміємо, як допомогає обмеження . По-перше, трохи спрощується критерій перевірки, описаний у другому пункті: . По-друге, можна помітити, що коли усі , з кожною позицією необхідно буде зробити хоча б одну операцію. Це означає, що у випадку, коли , відповідь буде . Дійсно, припустимо що існує якась оптимальна відповідь. Оскільки с кожною позицією була виконана хоч одна операція, можемо зменшити кількість операцій з кожною позицією на . Відповідь залишиться валідною, оскільки кожне не збільшиться. Тому ми отримали рішення з меншою кількістю операцій, що протиречить припущенню оптимальності відповіді.
Тепер розглянемо випадок коли . Припустимо, що рівно за операцій можна зробити усі числа недодатними. Тоді неважко побачити, що за операцій усі числа також можна зробити недодатними. Дійсно, можна просто зробити ще по одній операції з кожною позицією , після чого значення на усіх позиціях зменшаться на . Саме тому можна перебрати остачу від відповіді при діленні на , і зробити бінарний пошук на числах з такою остачею. Складність такого рішення .
Розв'язок: https://pastebin.com/kgUTa61U
Блок 5
На відміну від попереднього рішення, будемо перебирати остачі () від відповіді при діленні на у випадковому порядку. Також будемо підтримувати мінімальну знайдену відповідь серед усіх остач, що були розглянути попередньо. Тоді перед запуском бінарного пошуку на черговій остачі перевірими, чи покращуються взагалі відповідь. Для цьго необхідно перевірити описаний раніше критерій на максимальному числі меншим за з остачею . Тільки у випадку, коли критерій виконується, треба запускати бінарний пошук. Можна довести, у такому рішенні бінарний пошук буде запускатися разів, а тому загальна складність — .
Розв'язок: https://pastebin.com/D8KpR3ZX
Блок 6
Для прискорення попереднього рішення навчимося рахувати суму швидше ніж за .
Для цього помітимо, що . Значення не залежить від , а тому його можна підрахувати один раз до виконання всіх перевірок. Значення можна підрахувати як . Нехай , та . Тоді неважко побачити, що значення буде дорівнювати у випадку, коли , дорівнювати , коли , та інакше. Тому значення можна підрахувати як кількість чисел у масиві , що більше або дорівнюють плюс кількість чисел у масиві , що більше . Ці кількості можна знайти за допомогою бінарного пошуку, якщо попередньо відсортувати масив .
Таким чином, ми навчилися перевіряти критерій за , що набагато швидше . Загальна складність рішення — .
Розв'язок: https://pastebin.com/9wHi9fdg
Блок 7
Для прискорення попереднього рішення достатньо використати ідею, що була описана у п'ятому пункті. А саме необхідно запускати бінарний пошук тільки у випадку, коли відповідь для чергової остачі покращується. Складність такого рішення — .
Розв'язок: https://pastebin.com/N7yFLqYE
Блок 8
Для зручності будемо вважати, що усі числа відсортовані за спаданням. В останніх чотирьох блоках числа могли бути від'ємними, але насправді це не дуже сильно ускладнює задачу. Дійсно, позначимо через — максимальне число не більше за таке, що . Тоді неважко довести, що хоча б одна операція могла бути виконана максимум з позиціями (можна провести доведення, аналогічне доведенню з пункту ). Це означає, що з останніми позиціями не було проведено жодної операції.
Тоді для перших чисел можна розв'язати задачу так само, як і у групі , а далі необхідно буде перевірити, що останні чисел залишаться недодатними після виконання знайденної кількості операцій.
Розв'язок: https://pastebin.com/WXaDSk8n
Блок 9
Для прискорення попереднього рішення достатньо використати ідею, що була описана у п'ятому пункті. Складність такого рішення — .
Розв'язок: https://pastebin.com/Eh5cfipg
Блок 10
Для прискорення квадратичного розв'язку необхідно навчитися швидко перевіряти критерій, описаній в пункті . Відмінність від розв'язку шостої групи полягає в тому, що можуть бути менше нуля, а тому деякі не повинні додавати від'ємні значення до суми.
Оскільки усі значення відсортовані за спаданням, то в першу чергу можна знайти максимальну позицію таку, що . Для усіх наступних позицій внесок в шукану суму буде дорівнюавти нулю, а тому про ці позиції можна просто забути. Для знайденого префіксу позицій можна використовувати ідею з пункту , але для цього потрібно навчитися швидко рахувати кількість чисел більших даного на префіксі. Це можна зробити за допомогою техніки «часткове каскадування». Ця техніка дозволяє відповідати не необхідні запити за той самий час та потребує часу та пам'яті на побудову. З її допомогою можна розв'язати задачу за час .
Розв'язок: https://pastebin.com/U4CQse1c
Блок 11
Для прискорення попереднього рішення достатньо використати ідею, що була описана у п'ятому пункті. Складність такого рішення — .
Розв'язок: https://pastebin.com/kjFkP61L
У цієї задачі також існує інше, більш просте, рішення, що було знайдено під час тестування задачі Соболєвим Євгеном. Основна ідея полягає в тому, що можна робити звичайний бінарний пошук по відповіді, але перевіряти, що відповідь уснує не у точці , а у вікні розміром на інтервалі . Для того, щоб швидко перевіряти критерій, описаний раніше у пункті , можна спочатку за час знайти значення суми при . Для того, щоб перараховути значення суми при збільшенні на 1, можна було помітити, що кожен доданок суми може збільшитися максимум один раз на . Дійсно, при збільшенні на 1, чисельник дробу збільшується на , а знаменник рівен . Оскільки виконується рівність , то . Саме тому при збільшенні на лише разів, значення дробу може збільшитися максимум на . Момент часу, у який це значення збільшиться, можна знайти за формулою, і у відповідний момент часу збільшити поточне значення суми на . Складність такого рішення — .
Розв'язок: https://pastebin.com/DTmqmKBM
Зауваження та цікаві факти:
При реалізації рішення потрібно дуже уважно слідкувати за операціями множення, щоб випадково не вийти за межі 64-бітного типу даних. Найбільш небезпечне місце, де може переповнитися 64-бітний тип — це множення на у функції перевірки (наприклад, якщо виставляти межі бінарного пошуку рівними ). Але можно помітити, що оскільки , то . Оскільки відповідь не перевищує (), то . Це означає, що у якості правої межі бінарного пошуку можна виставити значення та більше не думати про переповнення.
Спочатку ця задача була запропонована на позицію «
A
» з неправильним авторським рішенням, описаним у пункті (звичайним бінарним пошуком по відповіді). Після знаходження правильного розв'язку складність задачі різко зросла, і задача пересунулася на останню позицію.