Extend the randomized multiset to support expiration. Each inserted occurrence has a time-to-live (TTL), and expired items must be excluded automatically.
You are given time-stamped operations in non-decreasing time order.
Rules:
- ('insert', time, val, ttl): before processing the operation, remove every occurrence whose expiration time is <= time. Then insert val with expiration time (time + ttl). Return True if val had no active occurrence just before this insertion, otherwise return False.
- ('remove', time, val): before processing the operation, remove all expired occurrences. Then remove one active occurrence of val. If multiple active occurrences exist, remove the most recently inserted active occurrence of val. Return True if one was removed, otherwise False.
- ('getRandom', time, r): before processing the operation, remove all expired occurrences. If there are n active occurrences, return the value stored at index (r % n) of the internal active array. If there are no active occurrences, return None.
An occurrence is considered expired at any time t where t >= insert_time + ttl.
Return the result of every operation in order.
Examples
Input: [('insert', 1, 5, 5), ('insert', 2, 5, 2), ('getRandom', 3, 1), ('getRandom', 4, 0), ('remove', 5, 5), ('getRandom', 5, 0)]
Expected Output: [True, False, 5, 5, True, None]
Explanation: The second 5 expires at time 4, so only one 5 remains active when time reaches 4. After removing the remaining 5 at time 5, the multiset becomes empty.
Input: [('insert', 0, 1, 10), ('insert', 1, 2, 10), ('insert', 2, 1, 10), ('remove', 3, 1), ('getRandom', 3, 1), ('getRandom', 10, 0), ('getRandom', 11, 0)]
Expected Output: [True, True, False, True, 2, 2, None]
Explanation: The manual remove at time 3 deletes the most recently inserted active 1. Later operations show automatic expiration at times 10 and 11.
Input: [('insert', 5, 7, 0), ('getRandom', 5, 0), ('insert', 5, 7, 1), ('getRandom', 5, 3), ('getRandom', 6, 0), ('remove', 6, 7)]
Expected Output: [True, None, True, 7, None, False]
Explanation: Edge case: TTL = 0 means the inserted occurrence is already expired for the next operation at the same timestamp.
Input: [('insert', 1, -1, 2), ('insert', 2, 4, 5), ('getRandom', 2, 5), ('remove', 3, -1), ('getRandom', 6, 0), ('remove', 7, 4)]
Expected Output: [True, True, 4, False, 4, False]
Explanation: The value -1 expires exactly at time 3 before the remove is processed. The value 4 expires exactly at time 7 before its remove.