A Tree with User-Owned Locks

Quick Overview

A Tree with User-Owned Locks. Implement the persistent LockingTree class from a valid parent array rooted at node 0. lock(num,user) succeeds only when num itself is unlocked. unlock succeeds only for its owning user. upgrade succeeds only when num is unlocked, no strict ancestor is locked, and at least one strict descendant is locked by any user; on success lock num for user and unlock every descendant. Failed operations leave all locks unchanged.

A Tree with User-Owned Locks

Company: Juspay

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Other

### Problem Implement `LockingTree` on a valid parent-array tree rooted at node 0. `lock(num,user)` succeeds exactly when that node is unlocked and then records its owner. `unlock(num,user)` succeeds only for its current owner. `upgrade(num,user)` succeeds only if the target is unlocked, has no locked strict ancestor and has at least one locked strict descendant. A successful upgrade locks the target for the given user and unlocks all descendants regardless of their owners. A failed operation changes no lock state. ```cpp class LockingTree { public: LockingTree(vector<int>& parent); bool lock(int num, int user); bool unlock(int num, int user); bool upgrade(int num, int user); }; ``` ### Examples **Example 1:** ```text parent = [-1,0,0] Calls: lock(1,4), upgrade(0,7), unlock(1,4), unlock(0,7) Results: true, true, false, true Explanation: The upgrade clears node 1 and gives node 0 to user 7. ``` **Example 2:** ```text parent = [-1,0,1] Calls: lock(0,2), lock(2,3), upgrade(1,4), unlock(0,5) Results: true, true, false, false Explanation: Ordinary lock ignores ancestors; upgrade is blocked by locked ancestor 0, and user 5 does not own node 0. ``` ### Constraints - `2 <= parent.length <= 2000`; `parent[0] == -1`. - Other parent values and num are valid node indices; parent represents a tree. - `1 <= user <= 10^4`; at most 2000 total method calls. ### Clarifying Questions Only upgrade checks ancestors and descendants. Ordinary lock checks the target alone. Descendants and ancestors exclude the target itself. ```hint Inspect the structure Which checks must finish before upgrade changes any ownership? ``` ### Reasoning checkpoints - Keep ownership and state transitions correct across sequences of lock, unlock and upgrade calls. - Apply all three upgrade conditions before making changes, including descendants owned by other users. - Preserve the distinction between ordinary lock permissions and the stricter upgrade preconditions. ### Optional extensions How could you accelerate descendant-lock checks and clearing operations on a much larger tree?

Overview: A Tree with User-Owned Locks. Implement the persistent LockingTree class from a valid parent array rooted at node 0. lock(num,user) succeeds only when num itself is unlocked. unlock succeeds only for its owning user. upgrade succeeds only when num is unlocked, no strict ancestor is locked, and at least one strict descendant is locked by any user; on success lock num for user and unlock every descendant. Failed operations leave all locks unchanged.

Juspay logo
Juspay
Aug 9, 2026
mediumSoftware EngineerOtherCoding & Algorithms
0
0

Problem

Implement LockingTree on a valid parent-array tree rooted at node 0. lock(num,user) succeeds exactly when that node is unlocked and then records its owner. unlock(num,user) succeeds only for its current owner. upgrade(num,user) succeeds only if the target is unlocked, has no locked strict ancestor and has at least one locked strict descendant. A successful upgrade locks the target for the given user and unlocks all descendants regardless of their owners. A failed operation changes no lock state.

class LockingTree {
public:
    LockingTree(vector<int>& parent);
    bool lock(int num, int user);
    bool unlock(int num, int user);
    bool upgrade(int num, int user);
};

Examples

Example 1:

parent = [-1,0,0]
Calls: lock(1,4), upgrade(0,7), unlock(1,4), unlock(0,7)
Results: true, true, false, true
Explanation: The upgrade clears node 1 and gives node 0 to user 7.

Example 2:

parent = [-1,0,1]
Calls: lock(0,2), lock(2,3), upgrade(1,4), unlock(0,5)
Results: true, true, false, false
Explanation: Ordinary lock ignores ancestors; upgrade is blocked by locked ancestor 0, and user 5 does not own node 0.

Constraints

  • 2 <= parent.length <= 2000 ; parent[0] == -1 .
  • Other parent values and num are valid node indices; parent represents a tree.
  • 1 <= user <= 10^4 ; at most 2000 total method calls.

Clarifying Questions Guidance

Only upgrade checks ancestors and descendants. Ordinary lock checks the target alone. Descendants and ancestors exclude the target itself.

Reasoning checkpoints

  • Keep ownership and state transitions correct across sequences of lock, unlock and upgrade calls.
  • Apply all three upgrade conditions before making changes, including descendants owned by other users.
  • Preserve the distinction between ordinary lock permissions and the stricter upgrade preconditions.

Optional extensions

How could you accelerate descendant-lock checks and clearing operations on a much larger tree?