import csv
import random
import sys
import time
import threading


sys.setrecursionlimit(30000)
threading.stack_size(64*1024*1024)


def ll_insert(head, name, phone):
    """Добавляет запись или обновляет телефон, если имя уже существует. Возвращает новую голову списка."""
    curr = head
    while curr is not None:
        if curr["name"] == name:
            curr["phone"] = phone
            return head
        curr = curr["next"]

    new_node = {"name": name, "phone": phone, "next": head}
    return new_node

def ll_find(head, name):
    """Ищет узел по имени. Возвращает телефон или None."""
    curr = head
    while curr is not None:
        if curr["name"] == name:
            return curr["phone"]
        curr = curr["next"]
    return None

def ll_delete(head, name):
    """Удаляет узел по имени. Возвращает новую голову списка."""
    curr = head
    prev = None

    while curr is not None:
        if curr["name"] == name:
            if prev is None:
                return curr["next"]
            else:
                prev["next"] = curr["next"]
                return head
        prev = curr
        curr = curr["next"]

    return head

def ll_list_all(head):
    """Собирает все записи в список и сортирует их по имени."""
    records = []
    curr = head
    while curr is not None:
        records.append((curr["name"], curr["phone"]))
        curr = curr["next"]
    records.sort(key=lambda x: x[0])
    return records


def ht_create(size=1000):
    """Создает пустую хеш-таблицу заданного размера."""
    return [None] * size

def ht_insert(buckets, name, phone):
    """Вычисляет индекс бакета и вызывает ll_insert."""
    idx = abs(hash(name)) % len(buckets)
    buckets[idx] = ll_insert(buckets[idx], name, phone)

def ht_find(buckets, name):
    """Вычисляет индекс бакета и вызывает ll_find."""
    idx = abs(hash(name)) % len(buckets)
    return ll_find(buckets[idx], name)

def ht_delete(buckets, name):
    """Вычисляет индекс бакета и вызывает ll_delete."""
    idx = abs(hash(name)) % len(buckets)
    buckets[idx] = ll_delete(buckets[idx], name)

def ht_list_all(buckets):
    """Собирает записи из всех бакетов и сортирует их по имени."""
    records = []
    for head in buckets:
        curr = head
        while curr is not None:
            records.append((curr["name"], curr["phone"]))
            curr = curr["next"]
    records.sort(key=lambda x: x[0])
    return records


def bst_insert(root, name, phone):
    """Рекурсивно вставляет узел или обновляет телефон."""
    if root is None:
        return {"name": name, "phone": phone, "left": None, "right": None}

    if name == root["name"]:
        root["phone"] = phone
    elif name < root["name"]:
        root["left"] = bst_insert(root["left"], name, phone)
    else:
        root["right"] = bst_insert(root["right"], name, phone)

    return root

def bst_find(root, name):
    """Рекурсивный поиск по дереву."""
    if root is None:
        return None

    if name == root["name"]:
        return root["phone"]
    elif name < root["name"]:
        return bst_find(root["left"], name)
    else:
        return bst_find(root["right"], name)

def bst_delete(root, name):
    """Рекурсивное удаление узла из BST."""
    if root is None:
        return None

    if name < root["name"]:
        root["left"] = bst_delete(root["left"], name)
    elif name > root["name"]:
        root["right"] = bst_delete(root["right"], name)
    else:
        if root["left"] is None:
            return root["right"]
        if root["right"] is None:
            return root["left"]

        min_node = root["right"]
        while min_node["left"] is not None:
            min_node = min_node["left"]

        root["name"] = min_node["name"]
        root["phone"] = min_node["phone"]
        root["right"] = bst_delete(root["right"], min_node["name"])

    return root

def bst_list_all(root):
    """Центрированный обход дерева для сбора записей."""
    records = []
    def _inorder(node):
        if node is not None:
            _inorder(node["left"])
            records.append((node["name"], node["phone"]))
            _inorder(node["right"])

    _inorder(root)
    return records