This problem is a scheduling simulation. Tasks arrive one per second (task j arrives at second j), and each task must be assigned to the lightest available server, breaking ties by index. Once a server takes a task, it becomes busy for tasks[j] seconds. The challenge is tracking which servers are free and which are busy, and knowing exactly when busy servers become free again.
At any moment the solution needs two answers: which free server has the smallest weight (and smallest index on a tie), and which busy server becomes free the soonest. Both are min-heap queries, which is what drives the efficient approach below.
1 <= n, m <= 2 * 10^5 → With up to 200,000 servers and 200,000 tasks, scanning all servers for every task is O(m n) = 4 10^10 operations, too slow within typical time limits. This rules out the brute force at full scale and points to O(m log n).1 <= servers[i], tasks[j] <= 2 * 10^5 → Task durations reach 200,000 seconds, so the timeline can stretch far beyond m. Simulating second by second is not viable, so time must advance by jumping to the next event.Simulate the process exactly as described. For each task, scan all servers to find the lightest free one. Track each server's busy-until time in an array. When no server is free, find the one that finishes earliest and advance time to that moment.
For every task this scans all n servers to find the best free one, which is slow but correct, and it makes the rules concrete before optimizing.
freeAt of size n, initialized to 0. freeAt[i] stores the second when server i becomes free.j (arriving at second j):t = max(j, earliest freeAt value among all servers).freeAt[i] <= t, find the one with the smallest weight (ties broken by smallest index).ans[j] = bestServer and update freeAt[bestServer] = t + tasks[j].ans.The cost comes from the two linear scans per task. Replacing those scans with priority queues makes finding the lightest free server O(log n) instead of O(n).
The brute force repeats the same two queries for every task: which free server has the smallest weight, and which busy server finishes earliest. Both are min-heap operations.
Maintain two heaps. A free heap stores available servers, ordered by (weight, index). A busy heap stores occupied servers, ordered by finish time. When a task arrives, move any servers whose finish time has passed from the busy heap back to the free heap, then pop the top of the free heap to assign the task.
One case needs care. If no server is free when a task arrives, advance time to the earliest finish time in the busy heap rather than stepping through empty seconds. That earliest finish releases at least one server, so the free heap is non-empty afterward and the task can be assigned at that moment.
The invariant is that every server sits in exactly one heap, and the split matches the system state at the current time: a server is in the free heap if its finish time is at or before time, otherwise it is in the busy heap. Tasks are processed in arrival order, so when task j is handled, the free heap's top is the lightest free server by (weight, index), which is exactly the assignment rule.
Advancing time to the earliest busy finish time, rather than one second at a time, keeps the work tied to events (m task arrivals plus n server releases) instead of the timeline length, which can reach 4 * 10^10 seconds.
(weight, index) pairs.(finishTime, weight, index) entries.j:time = max(j, top of busy heap's finish time) if the free heap is empty. Otherwise, time = j.time back to the free heap.(time + tasks[j], weight, index) onto the busy heap.ans[j] = server index.ans.