Intuitive, Fully Explained, Clean Python Solution with SortedList
IntuitionIt's fairly intuitive that we need some sort of map (dict), to quickly query information about any task in our system. Great, so let's start by thinkin
# Intuition

It's fairly intuitive that we need some sort of map (`dict`), to quickly query information about any task in our system. Great, so let's start by thinking about what we should use as the keys. We should probably use something unique. Ok, what's a unique parameter for each task. Well, the `task_id`! Adding the `user_id` and `priority` as values, we now we have a data structure `self.task_to_user_priority` supporting $\mathcal{O}(1)$ lookups for any task. We can use this map to achieve desired functionality for the `__init__`, `add`, `edit`, and `rmv` functions.

We still have no way to quickly query the highest priority task, needed to implement `execTop`. First, we need something to quickly maintain an order for each task based on `priority` and `task_id`. That basically narrows us down to a heap and a `SortedList` (functionally identical to a "tree map" in other languages.) Second, we still want to remove tasks efficiently. A sorted list is the best way to do this, as we can simply remove the (key, value) pair from the list in constant time.

Now, the final way to really make this solution clean is to liberally utilize already-implemented methods to implement new ones. For instance, we implement `__init__` with `add`. We implement `edit` as an `add` and `rmv`. We implement `execTop` with `rmv`. Doing this, each method becomes much shorter (3-5 lines).

Time complexity is logarithmic for **every** method. Space complexity is linear, as we store information about each task in our map. 

EDIT: I am noticing the most common solutions are utilizing a heap. Note that many of these solutions, while achieving a faster time on leetcode, are slower in terms of Big-O, as the execTop function they use involve popping all the elements from the heap, resulting in an nlogn time solution.

# Code
```python3 []
# unclear specification: are the initial tasks unique? assume yes

class TaskManager:

    def __init__(self, tasks: List[List[int]]):
        self.num_tasks = 0

        # mapping with task_id -> user_id, priority
        self.task_to_user_priority = dict()

        # a sortedlist with values as priority, task_id to order tasks
        self.ordered_tasks = SortedList()

        for task in tasks:
            self.add(*task)

    def add(self, user_id: int, task_id: int, priority: int) -> None:
        self.task_to_user_priority[task_id] = (user_id, priority)
        self.ordered_tasks.add((priority, task_id))
        self.num_tasks += 1

    def edit(self, task_id: int, new_priority: int) -> None:
        user_id, _ = self.task_to_user_priority[task_id]
        self.rmv(task_id)
        self.add(user_id, task_id, new_priority)

    def rmv(self, task_id: int) -> None:
        _, priority = self.task_to_user_priority[task_id]
        del self.task_to_user_priority[task_id]
        self.ordered_tasks.remove((priority, task_id))
        self.num_tasks -= 1

    def execTop(self) -> int:
        if self.num_tasks == 0: return -1

        _, task_id = self.ordered_tasks[-1]
        user_id, _ = self.task_to_user_priority[task_id]
        self.rmv(task_id)

        return user_id

# Your TaskManager object will be instantiated and called as such:
# obj = TaskManager(tasks)
# obj.add(user_id,task_id,priority)
# obj.edit(task_id,new_priority)
# obj.rmv(task_id)
# param_4 = obj.execTop()
```
['Ordered Map', 'Sorting', 'Python', 'Python3']