Автор задачі: | Антон Тригуб |
Задачу підготував: | Ігнат Жаріхін |
Розбір написав: | Ігнат Жаріхін |
10pt
Блок 1(n = 3)
Очевидно, існує єдине можливе розбиття на три підмасиви, кожен розміром один елемент.
Блок 2(a_i \leq 1)
Спочатку вирішимо, які будуть суми в підмасивах. Нехай змінна означає кількість одиничок в масиві. Логічно, кожен підвідрізок зробити за сумою якомога ближче до \left\lfloor \frac{cnt}{3} \right\rfloor. Якщо cnt \mid 3, то все добре і ми знайшли суми. Інакше, у нас може бути ще чи залишкові одинички, які ми не розподілили нікуди. Якщо вона одна, додаємо її в будь-який підмасив, а якщо їх дві — розподіляємо їх в будь-які два різні підмасиви.
Коли ми знаємо суми, просто проходимось по масиву і додаємо наступний елемент в поточний підмасив. Якщо досягли його суми(а пропустити її ми не можемо, бо a_i \leq 1), зачиняємо його і відкриваємо наступний. Таким чином знаходимо межі підмасивів.
a+b=c
Блок 3(гарантується, відповідь )
Порахуємо повну суму масиву, нехай це . Додаткові обмеження цієї групи означають, що є таке розбиття, де всі три підмасиви мають суму \frac{sum}{3}. Будь-які підмасиви з іншою сумою нас взагалі не цікавлять.
Для кожного індексу порахуємо такий мінімальний індекс next_i \leq n(якщо він існує), що сума на відрізку дорівнює \frac{sum}{3}. Якщо не існує, запам'ятаємо це.
Проходимось по масиву, перебираючи початок першого підмасиву — . Якщо не існує next_i, то цей початок точно не підходить, пропускаємо. Тоді, нехай j = next_i. Аналогічно, обов'язково треба, аби next_j існував, бо інакше таке розбиття не підходить. Якщо ж він існує, ми знайшли всі три межі між підвірізками. Перші два з них мають суму \frac{sum}{3}, отже і третій має таку саму, тобто ми знайшли відповідь. Складність —
Блок 4(n \leq 100)
Повністю переберемо три початки підмасивів, як це запропоновано в «форматі вихідних даних». Коли маємо межі x, y, z, рахуємо суми просто проходом по масиву чи префіксними сумами. Складність — \mathcal{O}(n^4) чи \mathcal{O}(n^3), в залежності від того, який метод обрати.
Надалі, всі суми будемо рахувати за допомогою префіксних сум.
Блок 5(n \leq 2000) та 6(n \leq 5000)
Переберемо лише перші два індекси. Наразі за допомогою них ми розбили масив на два підвідрізки. Один з них залишаємо, і його суму рахуємо, нехай це буде . Тепер нам залишилось розбити другий підвідрізок ще на два: префікс і суфікс. Помітимо, що багато з цих розбиттів точно не оптимальні. Інтуїтивно, нам цікаво розбити масив на два максимально рівні за сумою. Теоретично, нехай ми розбили таким чином, що суми префікса і суфікса дорівнюють і відповідно. Без втрати загальності, нехай pref \leq suff. Припустимо, що один елемент масиву(той, що зараз на межі) можна перевести з суфікса в префікс(те саме, що змістити межу на один), і при цьому нерівність залишиться вірною. Формально, pref+x\leq suff-x. Нам завжди буде вигідно зробити цей перехід, тому що \min(s,pref)\leq min(s,pref+x) і \max(s,suff)\geq max(s,suff-x), а отже відповідь буде не гіршою. Єдиний момент, коли нам може бути не вигідно робити перехід, це коли знак в нерівності змінюється. Отже, треба фактично перевірити лише два випадки: найбільший префікс, сума якого менша за суму суфікса та навпаки, найбільший суфікс, сума якого менша за суму префіксу. Зі всіх інших можна перейти в ці, не погіршуючи відповідь.
Перший варіант реалізації: після перебору перших двох індексів бінарним пошуком шукаємо переломний момент в сумах, і перевіряємо ці два випадки. Складність — \mathcal{O}(n^2 \cdot\log n), проходить п'яту групу.
Другий варіант реалізації: Переломний момент шукаємо другим вказівником, який завжди рухається праворуч по циклічному масиву. Складність — \mathcal{O}(n^2), проходить шосту групу.
Блок 7(n \leq 10^5) та 8(без додаткових обмежень)
Нехай сума всіх елементів масиву це . Помітимо, що в будь-якому розбитті рівно одне з наступних двох тверджень правдиве:
або рівно два масиви мають суму \leq \left\lfloor \frac{sum}{3} \right\rfloor і третій має суму \geq \left\lfloor \frac{sum}{3} \right\rfloor,
або рівно два масиви мають суму \geq \left\lfloor \frac{sum}{3} \right\rfloor і третій має суму \leq \left\lfloor \frac{sum}{3} \right\rfloor.
Переберемо розріз масиву між двома підмасивами, що обидва мають суму, не більшу за третину . Аналогічно до доведення з попередньої групи, з усіх таких масивів вигідно взяти найбільші за сумою з обох сторін. Це можна зробити за допомогою бінарного пошуку або двома вказівниками. Суму третього відрізка рахуємо як залишок.
Аналогічно, перебираємо розріз між двома підмасивами, що обидва мають суму, більшу за третину , проте тепер мінімізуємо ці два підмасиви. Кінцева складність — \mathcal{O}(n\cdot\log n) з бінпошуком(7 група) та зі вказівниками(повне рішення).
З точки зору реалізації, може допомогти подвоїти масив, вставивши в кінець копію початкового. Тоді замість того, щоб переходити з останнього елементу до початкового, можна просто продовжувати обхід масиву, єдине що треба буде перевірити, це те, чи не накладається кінець третього підмасиву на перший.