Hashmap | Set | STLs  solving queries in O(logn)
when we see this problem map seems to be the promising choice to store the keys and the values , so basically we will make different map to store different rela
when we see this problem map seems to be the promising choice to store the keys and the values , so basically we will make different map to store different relations , and we can add edit and remove using the map , one small catch is since many tasks can have same priority so for priority to task mapping we will use map of int and set where we will store different task for a particular priority in a set so that we can return the task with highest task id in optimal way. Rest the code is self explanatory 
# Code
```cpp []
class TaskManager {
public:
 

// taskidtopriority - tp
// priorityToTasks - pt
// taskidtouserid - tu

    unordered_map<int,int>tp;
    map<int, set<int>> pt;  
    unordered_map<int,int>tu;
    TaskManager(vector<vector<int>>& tasks) {
        int n = tasks.size();
        for(int i=0;i<n;i++){
            int user = tasks[i][0];
            int task = tasks[i][1];
            int priority = tasks[i][2];
            tp[task] = priority;
            tu[task] = user;
           pt[priority].insert(task);
        }
        
    }
    
    void add(int userId, int taskId, int priority) {
        tp[taskId] = priority;
        pt[priority].insert(taskId);
        tu[taskId] = userId;
    }
    
    void edit(int taskId, int newPriority) {
        int old = tp[taskId];
         pt[old].erase(taskId);
         if (pt[old].empty()) {
            pt.erase(old);
        }
        tp[taskId] = newPriority;
       
      pt[newPriority].insert(taskId);
        
    }
    
    void rmv(int taskId) {
        int p = tp[taskId];
        pt[p].erase(taskId);
        if (pt[p].empty()) {
            pt.erase(p);
        }

        tp.erase(taskId);
        tu.erase(taskId);
    }
    
    int execTop() {
          if (pt.empty()) {
        return -1;
    }
      auto it = pt.rbegin(); 
    int highestPriority = it->first; 
   
    auto &taskSet = it->second;     
    int taskId = *taskSet.rbegin();  
    
    
    int user = tu[taskId];
         taskSet.erase(taskId);
         if (taskSet.empty()) {
        pt.erase(highestPriority);
    }
         tp.erase(taskId);
        tu.erase(taskId);
        return user;
    }
};

/**
 * 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();
 */
```
I have also made a detailed video explaining the problem
https://www.youtube.com/watch?v=cKOpOAXy1MA

['Design', 'Ordered Map', 'C++']