2286. Booking Concert Tickets in Groups
Description
A concert hall has n
rows numbered from 0
to n - 1
, each with m
seats, numbered from 0
to m - 1
. You need to design a ticketing system that can allocate seats in the following cases:
- If a group of
k
spectators can sit together in a row. - If every member of a group of
k
spectators can get a seat. They may or may not sit together.
Note that the spectators are very picky. Hence:
- They will book seats only if each member of their group can get a seat with row number less than or equal to
maxRow
.maxRow
can vary from group to group. - In case there are multiple rows to choose from, the row with the smallest number is chosen. If there are multiple seats to choose in the same row, the seat with the smallest number is chosen.
Implement the BookMyShow
class:
BookMyShow(int n, int m)
Initializes the object withn
as number of rows andm
as number of seats per row.int[] gather(int k, int maxRow)
Returns an array of length2
denoting the row and seat number (respectively) of the first seat being allocated to thek
members of the group, who must sit together. In other words, it returns the smallest possibler
andc
such that all[c, c + k - 1]
seats are valid and empty in rowr
, andr <= maxRow
. Returns[]
in case it is not possible to allocate seats to the group.boolean scatter(int k, int maxRow)
Returnstrue
if allk
members of the group can be allocated seats in rows0
tomaxRow
, who may or may not sit together. If the seats can be allocated, it allocatesk
seats to the group with the smallest row numbers, and the smallest possible seat numbers in each row. Otherwise, returnsfalse
.
Example 1:
Input ["BookMyShow", "gather", "gather", "scatter", "scatter"] [[2, 5], [4, 0], [2, 0], [5, 1], [5, 1]] Output [null, [0, 0], [], true, false] Explanation BookMyShow bms = new BookMyShow(2, 5); // There are 2 rows with 5 seats each bms.gather(4, 0); // return [0, 0] // The group books seats [0, 3] of row 0. bms.gather(2, 0); // return [] // There is only 1 seat left in row 0, // so it is not possible to book 2 consecutive seats. bms.scatter(5, 1); // return True // The group books seat 4 of row 0 and seats [0, 3] of row 1. bms.scatter(5, 1); // return False // There is only one seat left in the hall.
Constraints:
1 <= n <= 5 * 104
1 <= m, k <= 109
0 <= maxRow <= n - 1
- At most
5 * 104
calls in total will be made togather
andscatter
.
Solution
booking-concert-tickets-in-groups.py
class Node:
def __init__(self, start, end):
self.left = None
self.right = None
self.start = start
self.end = end
self.total = 0
self.mx = 0
class SegTree:
def __init__(self, n, val):
self.root = self.buildTree(0, n, val)
def buildTree(self, start, end, val):
if start > end: return None
if start == end:
node = Node(start, end)
node.total = val
node.mx = val
return node
node = Node(start, end)
mid = start + (end - start) // 2
node.left = self.buildTree(start, mid, val)
node.right = self.buildTree(mid + 1, end, val)
node.total = node.left.total + node.right.total
node.mx = max(node.left.mx, node.right.mx)
return node
def update(self, index: int, val: int) -> None:
self.updateR(self.root, index, val)
def updateR(self, node, index, val):
if node.start == node.end:
node.total -= val
node.mx -= val
else:
mid = node.start + (node.end - node.start) // 2
if index <= mid:
self.updateR(node.left, index, val)
else:
self.updateR(node.right, index, val)
node.total = node.left.total + node.right.total
node.mx = max(node.left.mx, node.right.mx)
def sumRange(self, left: int, right: int) -> int:
return self.sumRangeR(self.root, left, right)
def sumRangeR(self, node, left, right):
if not node or node.start > right or node.end < left: return 0
if node.start >= left and node.end <= right: return node.total
l = self.sumRangeR(node.left, left, right)
r = self.sumRangeR(node.right, left, right)
return l + r
def maxQuery(self, k, maxRow, seats):
def maxQueryHelper(node):
if node.start == node.end:
if node.end > maxRow or node.total < k:
return []
if node.end <= maxRow and node.total >= k:
return [node.end, seats - node.total]
return maxQueryHelper(node.left) if node.left.mx >= k else maxQueryHelper(node.right)
return maxQueryHelper(self.root)
class BookMyShow:
def __init__(self, n: int, m: int):
self.seg = SegTree(n - 1, m)
self.seats = [m] * n
self.m = m
self.n = n
self.startRow = 0
def gather(self, k: int, maxRow: int) -> List[int]:
res = self.seg.maxQuery(k, maxRow, self.m)
if res:
row = res[0]
self.seg.update(row, k)
self.seats[row] -= k
return res
def scatter(self, k: int, maxRow: int) -> bool:
if self.seg.sumRange(0, maxRow) < k:
return False
index = self.startRow
curr = 0
while curr < k:
rest = k - curr
if rest >= self.seats[index]:
self.seg.update(index, self.seats[index])
curr += self.seats[index]
self.seats[index] = 0
index += 1
self.startRow = index
else:
self.seg.update(index, rest)
self.seats[index] -= rest
curr += rest
return True
# Your BookMyShow object will be instantiated and called as such:
# obj = BookMyShow(n, m)
# param_1 = obj.gather(k,maxRow)
# param_2 = obj.scatter(k,maxRow)