[Python] hash map to find the task list, prioirty queue to find the next prioirty; Explained
Intuition(1) self.task_map maps a taskID to a (priority, userID) tuple
(2) self.prioirty_map maps a priorityID to a list of taskIDs. the list is managed in the
# Intuition
(1) `self.task_map` maps a `taskID` to a `(priority, userID)` tuple
(2) `self.prioirty_map` maps a `priorityID` to a list of `taskID`s. the list is managed in the ascending order, so that we can quick find the next taskID for execution.
(3) we use `self.min_heap` to order the existing priorities.

Adding a new task into the manager, we can update the above three data structures accordingly.

Removing one task, we just need to delelet the taskID in the self.task_map, and update the self.priority_map.

Editing one task is a sequence of removing the task with old priority, and adding the same task with new priority.

See the code for details.

# Code
```python3 []
class TaskManager:

    def __init__(self, tasks: List[List[int]]):
        self.task_map = dict()  # taskid -> (priority, userid)
        self.priority_map = collections.defaultdict(list)  # prioirty -> (taskid)
        self.min_heap = []  # priority queue

        for uid, tid, pid in tasks:
            self.add(uid, tid, pid)


    def add(self, userId: int, taskId: int, priority: int) -> None:
        self.task_map[taskId] = (priority, userId)
        if priority in self.priority_map:
            bisect.insort_left(self.priority_map[priority], taskId)
        else:
            heapq.heappush(self.min_heap, -priority)
            self.priority_map[priority].append(taskId)


    def edit(self, taskId: int, newPriority: int) -> None:
        orig_pid, uid = self.task_map[taskId]
        self.rmv(taskId)
        self.add(uid, taskId, newPriority)
        

    def rmv(self, taskId: int) -> None:
        pid, uid = self.task_map[taskId]
        del self.task_map[taskId]
        self.priority_map[pid].pop(bisect.bisect(self.priority_map[pid], taskId) - 1)


    def execTop(self) -> int:
        while self.min_heap and len(self.priority_map[-self.min_heap[0]]) == 0:
            pid = -heapq.heappop(self.min_heap)
            del self.priority_map[pid]

        uid = -1
        if self.min_heap:
            hi_priority = -self.min_heap[0]
            tid = self.priority_map[hi_priority][-1]
            _, uid = self.task_map[tid]
            self.rmv(tid)
        return uid


# Your TaskManager object will be instantiated and called as such:
# obj = TaskManager(tasks)
# obj.add(userId,taskId,priority)
# obj.edit(taskId,newPriority)
# obj.rmv(taskId)
# param_4 = obj.execTop()
```
['Hash Table', 'Heap (Priority Queue)', 'Python3']