Implement Hierarchical Region Access Overrides
PinterestSoftware Engineer · Technical ScreenLast updated
Design and implement a regional access control system that handles time-based access overrides on a static tree hierarchy with out-of-order updates.
Problem Statement
Geographic regions are modeled as a static tree hierarchy where each region has at most one parent (e.g., "GLOBAL" -> "NA" -> "US" -> "CA"). Access permissions (True for granted, False for denied) set at any node inherit down to all of its descendants.
Over time, administrators can set access overrides at any node with an associated integer timestamp. An override takes effect at its given timestamp and persists indefinitely unless overridden. Because log events may be delivered out of order, override records can arrive in any order of their timestamps.
When checking whether access is granted to a region at a query timestamp t:
- Consider all overrides on the path from the root down to the target region with an override
timestamp <= t. - The override with the strictly largest
timestampdetermines the access permission. - If two overrides on the path have the exact same
timestamp, the one closest to the target region (deepest in the tree) takes precedence. - If no overrides on the path occurred at or before
t, access defaults toFalse.
Implement the RegionAccessManager class:
class RegionAccessManager:
def __init__(self, hierarchy: dict[str, str | None]):
"""
Initializes the hierarchy where hierarchy[region] = parent_region.
Root regions have None as their parent.
"""
pass
def set_override(self, region: str, allowed: bool, timestamp: int) -> None:
"""
Records an access override for the specified region starting at timestamp.
"""
pass
def has_access(self, region: str, timestamp: int) -> bool:
"""
Returns whether access is permitted for region at query timestamp.
"""
pass
Examples
Example 1
hierarchy = {
"GLOBAL": None,
"NA": "GLOBAL",
"US": "NA",
"CA": "US"
}
manager = RegionAccessManager(hierarchy)
manager.set_override("GLOBAL", True, 10)
manager.set_override("US", False, 20)
# Query at t=15 for "CA":
# Path: GLOBAL (t=10, True)
manager.has_access("CA", 15) # Returns True
# Query at t=25 for "CA":
# Path: GLOBAL (t=10, True), US (t=20, False)
# Max timestamp is 20 (US), which is False
manager.has_access("CA", 25) # Returns False
# Out-of-order override set at "NA" with timestamp 30
manager.set_override("NA", True, 30)
# Query at t=35 for "CA":
# Path: GLOBAL (10, True), NA (30, True), US (20, False)
# Max timestamp is 30 (NA), which is True
manager.has_access("CA", 35) # Returns True
Constraints
- Number of regions
N <= 10,000 - Maximum tree depth
D <= 50 - Total calls to
set_overrideandhas_access<= 50,000 1 <= timestamp <= 10^9- All region names are non-empty strings of alphanumeric characters.
- The hierarchy is guaranteed to form a valid forest/tree (no cycles).
Hints
Hint 1
Since the tree hierarchy is static and depth D is small (<= 50), traversing from a region up to the root on each query takes O(D) steps.
Hint 2
For each region, maintain its overrides in chronological order so you can use binary search to quickly find the latest override with timestamp <= t.
Hint 3
During a query, inspect every ancestor up to the root, find the latest effective override at each node using binary search, and select the one with the maximum timestamp (breaking ties by node depth).
Follow-up questions
- How would you optimize `has_access` if the tree depth D could be as large as N (e.g., up to 100,000 nodes in a degenerate line)?
- What concurrency or thread-safety primitives would you introduce if reads and writes happen simultaneously across multiple threads?
- If overrides also had an expiration timestamp (e.g., an interval `[start_time, end_time)`), how would your data structure and query logic change?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.