Як запропонував @randomA, ми продовжимо дві фази: Спочатку ми знаходимо набір паличок, які будуть вирізані, а потім мінімізуємо кількість надрізів.
Як і в спеціальному випадку у питанні, ми сортуємо / називаємо палички так, щоб . Це займає час .L1≥L2≥⋯≥LnO(nlogn)
Як вказував @ user1990169, нам ніколи не доводиться вирізати шматок .i≥k
На першому етапі ми використовуємо двійковий пошук, щоб знайти число , , щоб палички можна було розрізати на принаймні шматочки розміром (плюс кілька менших шматочків) , але палички не можна розрізати на шматочки розміром . Це займе час .s1≤s≤k1,…,skLs1,…,s−1kLs−1O(klogk)
Якщо , це значення є оптимальним розміром, і ми можемо пропустити другу фазу.Ls−1=Ls
В іншому випадку ми знаємо, що оптимальний розмір задовольняє а якщо то результатом розрізання хоча б однієї палички на шматки рівних розмірів. Фаза два визначатиме :oLs−1>o≥Lso>Lsoo
Для кожної палички , визначте набір розмірів кандидатів таким чином: Якщо різання на шматки розміром перетворює палицю на шматочки (включаючи коротший, якщо такий є), то кандидати на це stick - всі значення , де і . (Дивіться відповідь @ user1990169, чому це єдиний розмір кандидата.)i1≤i≤sLsriLijj≤riLij<Ls−1
Підтримуйте для кожного кандидата розмір, як часто це траплялося. Використовуючи збалансоване дерево пошуку, це можна зробити в , оскільки загальна кількість розмірів кандидатів пов'язана з .O(klogk)∑iri≤2k
Тепер розмір кандидата, який траплявся найчастіше і призводить до дійсного скорочення, - це той, який дає нам оптимальне рішення. Крім того, якщо будь-який розмір кандидата призводить до дійсного скорочення, будь-який менший розмір також призведе до дійсного висічення.
Таким чином, ми можемо знову використовувати двійковий пошук, щоб знайти найбільшу довжину кандидата, яка призводить до дійсного скорочення . Тоді ми повторюємо набір довжин кандидатів до цього порогу і знаходимо ту, яка має найбільшу множину серед них в .O(klogk)O(k)
Загалом ми отримуємо час виконання в або , якщо ігнорувати (або не робити цього) початковий тип.O(nlogn)O(klogk)