Problem Description
Given an array “blocks” where blocks[i] is the time required to build the i‑th block, and an integer “split” representing the cost for any worker to split into two workers, determine the minimum total time required to build all blocks. Initially there is one worker; a worker may either build one block (and then go home) or split (which produces two workers, at a cost of “split” time for that worker). Notice that if several workers split concurrently the cost is incurred only once in that time unit. The goal is to schedule splits and assignments so that each block is built exactly by one worker and the overall time (which is the maximum time taken on any branch) is minimized.
Key Insights
- To build more than one block, splitting is necessary; however, each split “ages” the worker (increases its “depth”) so that the subsequent block built by that worker will finish later.
- The time needed on a branch equals (number of splits on that branch)×split + block’s building time.
- If we decide on a total allowed time T, then a block with build time b must be built along a branch that had at most floor((T – b)/split) splits.
- An optimal strategy is equivalent to “assigning” each block to a leaf in a binary splitting tree – the leaf’s “depth” is the number of splits used before building.
- One may show that if we want to produce n leaves (n blocks) in an optimally “balanced” way then the best achievable multiset of depths is the one obtained by “greedily splitting” the available worker with the smallest depth until n leaves are available.
- Then, by sorting the blocks in descending order and pairing the largest block with the leaf that has the smallest depth (i.e. the “most efficient” branch), one sees that a candidate time T is feasible if for every block (after appropriate ordering) the allowed splits for that block (floor((T – block)/split)) is at least the corresponding optimal leaf depth.
Space and Time Complexity
Time Complexity: O(n log n + n log nTree) per feasibility check (n up to 1000) and multiplied by binary search iterations. Overall it is O(n (log n + log(MaxTime))). Space Complexity: O(n) for sorting and storing the optimal depths.
Solution
We solve the problem using binary search on the total allowed time T. For a candidate T, we need to decide if we can “assign” every block to a worker branch such that for a block with build time b, the branch used had at most allowed splits L = floor((T – b)/split). (If T < b then T is not feasible.) To “simulate” the worker‐splitting process optimally, we generate the multiset of the minimum branch‐depths possible for n blocks. This is done by starting with one worker (depth 0) and repeatedly “splitting” (removing a worker with the smallest depth and replacing it with two workers of depth+1) until we have exactly n leaves. We then sort these optimal depths in non‐decreasing order. Also, for each block we compute its allowed maximum number of splits as floor((T – block)/split); sorting these allowed values in non‑decreasing order (so that the block with the largest build time is paired with the smallest depth) allows us to “match” the leaves with the blocks. If every optimal leaf depth is less than or equal to the allowed splits for its corresponding block, then T is feasible.
The binary search runs over T in the range [min(blocks), max(blocks) + split * n] to be safe. The final answer is the minimum T for which a feasible assignment exists.
We now show code solutions in Python, JavaScript, C++ and Java with detailed comments.