Problem Description
Design a ticket booking system for a concert hall with n rows and m seats per row. The system must support two operations:
- gather(k, maxRow): Allocate k consecutive seats in a single row (with row index ≤ maxRow) and return the row and starting seat index if possible.
- scatter(k, maxRow): Allocate k seats (not necessarily consecutive) among rows 0 to maxRow, using seats in the smallest rows and leftmost positions available.
If allocation is not possible, return an empty result (for gather) or false (for scatter).
Key Insights
- Each row can be viewed as having a contiguous block of available seats starting from a pointer (initially 0) because seats are allocated from left to right.
- For gather queries, we need to quickly find the first row (≤ maxRow) that has at least k consecutive available seats; this can be done by maintaining a segment tree (or BIT) that tracks the maximum contiguous seats per row.
- For scatter queries, we require the total sum of available seats in rows [0, maxRow] to be at least k; if so, we then allocate seats row by row.
- A segment tree is ideal since it can support both range maximum queries (for gather) and range sum queries (for scatter) with efficient point updates.
- The allocation order (smallest row and seat number) is naturally maintained if each row allocates from its leftmost available seat.
Space and Time Complexity
Time Complexity: Each gather or scatter call performs O(log n) work per segment tree query/update (gather uses binary-search on the tree, and scatter may update several rows but overall remains efficient given constraints).
Space Complexity: O(n) for maintaining the segment tree and auxiliary arrays.
Solution
The solution maintains an array where each entry indicates the number of available consecutive seats in that row (initially m for every row). A segment tree is built on top of this array providing two capabilities:
- Query the maximum available seats in any row for a given range (to support gather).
- Query the total sum of available seats in any range (to support scatter).
For a gather(k, maxRow) call, the segment tree is queried over the range [0, maxRow] to check if any row has at least k available consecutive seats. If found, a binary search over the segment tree identifies the earliest row with this property. The starting seat in that row is computed as m minus the current available seats, and the row’s available count is decremented by k followed by an update in the segment tree.
For a scatter(k, maxRow) call, the segment tree is queried for the total available seats in the range [0, maxRow]. If the sum is at least k, allocation proceeds row by row—each row contributes as many seats as it can (from its leftmost available seat), updating the segment tree accordingly, until k seats have been allocated.