dont use threading to slve this approach use custom and aussume GIL does not exist 
"""
Let’s say you are running the lock/unlock in a multi core machine. Now you
want to let multiple threads to run lock() As we saw in part A, locking a
node has multiple validations inside. Will doing lock on two nodes
cause a race condition. If yes, how will you solve it. In short, how do
make the lock() function thread safe? - Multiple threads running it
simultaneously shouldn’t not affect the correctness. - Try to make the
critical sections more granular. ie. don’t create any big
atomic/synchronised blocks that will make parallelism suffer. Consider
each operation is atomic.


"""
"""
import sys

class Node:
    def __init__(self, name):
        self.name = name
        self.parent = None
        self.children = []
        self.isLocked = False
        self.locked_uid = None
        self.locked_descendant_count = 0  # Number of locked descendants

class Tree:
    def __init__(self, m, n, name_list):
        self.node_map = {}
        self.node_list = [Node(name) for name in name_list]
        for node in self.node_list:
            self.node_map[node.name] = node
        
        # Building an m-ary tree assuming breadth-first insertion
        for i in range(n):
            current = self.node_list[i]
            for j in range(1, m+1):
                child_index = m * i + j
                if child_index >= n:
                    break
                child = self.node_list[child_index]
                current.children.append(child)
                child.parent = current
        
    def lock(self, node, uid):
        if node.isLocked:
            return False
        
        # Check if any ancestor is locked
        current = node.parent
        while current:
            if current.isLocked:
                return False
            current = current.parent
        
        if node.locked_descendant_count > 0:
            return False
        
        # Lock the node
        node.isLocked = True
        node.locked_uid = uid
        
        # Update locked_descendant_count for all ancestors
        current = node.parent
        while current:
            current.locked_descendant_count += 1
            current = current.parent
        
        return True
    
    def unlock(self, node, uid):
        if not node.isLocked or node.locked_uid != uid:
            return False
        
        # Unlock the node
        node.isLocked = False
        node.locked_uid = None
        
        # Update locked_descendant_count for all ancestors
        current = node.parent
        while current:
            current.locked_descendant_count -= 1
            current = current.parent
        
        return True
    
    def upgrade(self, node, uid):
        if node.isLocked:
            return False
        
        # Check if any ancestor is locked
        current = node.parent
        while current:
            if current.isLocked:
                return False
            current = current.parent
        
        if node.locked_descendant_count == 0:
            return False
        
        # Collect all locked descendants
        locked_nodes = []
        self._collect_locked_descendants(node, locked_nodes)
        
        if not locked_nodes:
            return False
        
        # Ensure all locked descendants have the same uid
        for locked_node in locked_nodes:
            if locked_node.locked_uid != uid:
                return False
        
        # Unlock all locked descendants
        for locked_node in locked_nodes:
            locked_node.isLocked = False
            locked_node.locked_uid = None
            # Update locked_descendant_count for ancestors of each unlocked node
            ancestor = locked_node.parent
            while ancestor:
                ancestor.locked_descendant_count -= 1
                ancestor = ancestor.parent
        
        # Lock the current node
        node.isLocked = True
        node.locked_uid = uid
        
        # Update locked_descendant_count for all ancestors
        current = node.parent
        while current:
            current.locked_descendant_count += 1
            current = current.parent
        
        return True
    
    def _collect_locked_descendants(self, node, locked_nodes):
    # DFS to collect all locked descendants
        stack = []
        stack.append(node)
        while stack:
            current = stack.pop()
            for child in current.children:
                if child.locked_descendant_count == 0 and not child.isLocked:
                    continue  # No need to traverse this subtree
                if child.isLocked:
                    locked_nodes.append(child)
                stack.append(child)    
                
    def process_queries(self, queries):
        results = []
        for query in queries:
            parts = query.strip().split()
            if len(parts) != 3:
                results.append('false')
                continue
            operation, node_name, uid_str = parts
            try:
                uid = int(uid_str)
            except ValueError:
                results.append('false')
                continue
            node = self.node_map.get(node_name, None)
            if not node:
                results.append('false')
                continue
            if operation == "1":
                result = self.lock(node, uid)
            elif operation == "2":
                result = self.unlock(node, uid)
            elif operation == "3":
                result = self.upgrade(node, uid)
            else:
                result = False  # Invalid operation
            results.append('true' if result else 'false')
        return results

def main():
    import sys
    import sys
    input = sys.stdin.read
    data = input().splitlines()
    ptr = 0
    if ptr >= len(data):
        sys.exit()
    n = int(data[ptr]); ptr +=1
    if ptr >= len(data):
        sys.exit()
    m = int(data[ptr]); ptr +=1
    if ptr >= len(data):
        sys.exit()
    q = int(data[ptr]); ptr +=1
    name_list = []
    for _ in range(n):
        if ptr >= len(data):
            break
        name_list.append(data[ptr].strip())
        ptr +=1
    queries = []
    for _ in range(q):
        if ptr >= len(data):
            break
        queries.append(data[ptr].strip())
        ptr +=1
    tree = Tree(m, n, name_list)
    results = tree.process_queries(queries)
    for res in results:
        print(res)

if __name__ == "__main__":
    main()
"""