Operations on Tree

medium tree design bfs

Problem

You are given a rooted tree of n nodes (0 to n−1) described by a parent array, where parent[i] is the parent of node i and the root has parent −1. Design a structure with three operations. lock(num, user) locks node num for user only if it is currently unlocked. unlock(num, user) unlocks node num only if it is currently locked by that same user. upgrade(num, user) locks node num for user only if node num is unlocked, has at least one locked descendant, and has no locked ancestor; on success it also unlocks every descendant. Each call returns true on success and false otherwise.

Inputparent = [-1,0,0,1,1,2,2]; lock(2,2); unlock(2,3); unlock(2,2); lock(4,5); upgrade(0,1)
Output[true, false, true, true, true]
lock(2,2) succeeds. unlock(2,3) fails because node 2 is held by user 2, not 3. unlock(2,2) succeeds. lock(4,5) succeeds. upgrade(0,1) succeeds: node 0 is free, has a locked descendant (4), and no locked ancestor — so 0 is locked for user 1 and node 4 is unlocked.

class LockingTree:
    def __init__(self, parent):
        self.parent = parent
        self.lock = [0] * len(parent)
        self.children = [[] for _ in parent]
        for i, p in enumerate(parent):
            if p != -1:
                self.children[p].append(i)

    def lock(self, num, user):
        if self.lock[num]:
            return False
        self.lock[num] = user
        return True

    def unlock(self, num, user):
        if self.lock[num] != user:
            return False
        self.lock[num] = 0
        return True

    def upgrade(self, num, user):
        a = self.parent[num]
        while a != -1:
            if self.lock[a]:
                return False
            a = self.parent[a]
        found = False
        stack = [num]
        while stack:
            node = stack.pop()
            for c in self.children[node]:
                if self.lock[c]:
                    found = True
                    self.lock[c] = 0
                stack.append(c)
        if self.lock[num] or not found:
            return False
        self.lock[num] = user
        return True
class LockingTree {
  constructor(parent) {
    this.parent = parent;
    this.lock = new Array(parent.length).fill(0);
    this.children = parent.map(() => []);
    parent.forEach((p, i) => { if (p !== -1) this.children[p].push(i); });
  }
  lock(num, user) {
    if (this.lock[num]) return false;
    this.lock[num] = user;
    return true;
  }
  unlock(num, user) {
    if (this.lock[num] !== user) return false;
    this.lock[num] = 0;
    return true;
  }
  upgrade(num, user) {
    let a = this.parent[num];
    while (a !== -1) {
      if (this.lock[a]) return false;
      a = this.parent[a];
    }
    let found = false;
    const stack = [num];
    while (stack.length) {
      const node = stack.pop();
      for (const c of this.children[node]) {
        if (this.lock[c]) { found = true; this.lock[c] = 0; }
        stack.push(c);
      }
    }
    if (this.lock[num] || !found) return false;
    this.lock[num] = user;
    return true;
  }
}
class LockingTree {
    int[] parent, lock;
    List<List<Integer>> children;
    public LockingTree(int[] parent) {
        this.parent = parent;
        lock = new int[parent.length];
        children = new ArrayList<>();
        for (int i = 0; i < parent.length; i++) children.add(new ArrayList<>());
        for (int i = 0; i < parent.length; i++)
            if (parent[i] != -1) children.get(parent[i]).add(i);
    }
    public boolean lock(int num, int user) {
        if (lock[num] != 0) return false;
        lock[num] = user;
        return true;
    }
    public boolean unlock(int num, int user) {
        if (lock[num] != user) return false;
        lock[num] = 0;
        return true;
    }
    public boolean upgrade(int num, int user) {
        for (int a = parent[num]; a != -1; a = parent[a])
            if (lock[a] != 0) return false;
        boolean found = false;
        Deque<Integer> stack = new ArrayDeque<>();
        stack.push(num);
        while (!stack.isEmpty()) {
            int node = stack.pop();
            for (int c : children.get(node)) {
                if (lock[c] != 0) { found = true; lock[c] = 0; }
                stack.push(c);
            }
        }
        if (lock[num] != 0 || !found) return false;
        lock[num] = user;
        return true;
    }
}
class LockingTree {
    vector<int> parent, lock_;
    vector<vector<int>> children;
public:
    LockingTree(vector<int>& parent) : parent(parent) {
        lock_.assign(parent.size(), 0);
        children.resize(parent.size());
        for (int i = 0; i < (int)parent.size(); i++)
            if (parent[i] != -1) children[parent[i]].push_back(i);
    }
    bool lock(int num, int user) {
        if (lock_[num]) return false;
        lock_[num] = user;
        return true;
    }
    bool unlock(int num, int user) {
        if (lock_[num] != user) return false;
        lock_[num] = 0;
        return true;
    }
    bool upgrade(int num, int user) {
        for (int a = parent[num]; a != -1; a = parent[a])
            if (lock_[a]) return false;
        bool found = false;
        vector<int> stack = { num };
        while (!stack.empty()) {
            int node = stack.back(); stack.pop_back();
            for (int c : children[node]) {
                if (lock_[c]) { found = true; lock_[c] = 0; }
                stack.push_back(c);
            }
        }
        if (lock_[num] || !found) return false;
        lock_[num] = user;
        return true;
    }
};
Time: O(n) per upgrade Space: O(n)