Как подсказывает @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)