Easiest AC || Maps and priority queue or max heap
Intuition
Use a priority queue (maxheap) that stores {userId, taskId, priority}. This is sorted as mentioned in the question (max priority first, or greater use
# Intuition
<!-- Describe your first thoughts on how to solve this problem. -->
- Use a priority queue (maxheap) that stores {userId, taskId, priority}. This is sorted as mentioned in the question (max priority first, or greater user id if priorities are equeal). 
- Everything that goes into the priority queue is marked as open in a map named `isopen`. If this is edited or removed, it is changed to false in the map.
- Another map `m` is used to store the latest priority and userId of the corresponding taskId.

# Code
```cpp []
class TaskManager {
public:
    struct Compare {
    bool operator()(const vector<int>& a, const vector<int>& b) {
        if (a[2] == b[2]) {
            return a[1] < b[1];
        }
        return a[2] < b[2];
    }
};
    priority_queue<vector<int>, vector<vector<int>>, Compare> q;  // userid, taskid, priority
    map<int, vector<int>> m;
    map<vector<int>, bool> isopen;

public:
    TaskManager(vector<vector<int>>& tasks) {
        for (auto& t : tasks) {
            int userId = t[0];
            int taskId = t[1];
            int priority = t[2];
            q.push(t);
            m[taskId] = {userId, priority};
            isopen[t] = true;
        }
    }

    void add(int userId, int taskId, int priority) {
        q.push({userId, taskId, priority});
        m[taskId] = {userId, priority};
        isopen[{userId, taskId, priority}] = true;
    }

    void edit(int taskId, int newPriority) {
        vector<int> v = m[taskId];
        int userId = v[0];
        int priority = v[1];
        if(priority == newPriority) return;
        
        q.push({userId, taskId, newPriority});
        isopen[{userId, taskId, newPriority}] = true;
        
        m[taskId] = {userId, newPriority};

        isopen[{userId, taskId, priority}] = false;
        
    }

    void rmv(int taskId) {
        vector<int> v = m[taskId];
        int userId = v[0];
        int priority = v[1];
        isopen[{userId, taskId, priority}] = false;
        m.erase(taskId);
    }

    int execTop() {
        while (!q.empty()) {
            if(isopen[q.top()]==false){
                q.pop();
                continue;
            }
            else{
                break;
            }
        }
        if (!q.empty()) {
            vector<int> t = q.top();
            q.pop();
            
            int userId = t[0];
            int taskId = t[1];
            
            m.erase(taskId);

            isopen[t]=false;
            return userId;
        }
        return -1; 
    }
};

/**
 * Your TaskManager object will be instantiated and called as such:
 * TaskManager* obj = new TaskManager(tasks);
 * obj->add(userId,taskId,priority);
 * obj->edit(taskId,newPriority);
 * obj->rmv(taskId);
 * int param_4 = obj->execTop();
 */
```
['Ordered Map', 'Heap (Priority Queue)', 'C++']