Step-by-Step Solution using Set, Map and STL 
IntuitionDo every process as mentioned keeping a set which manages the priority status of the process in descending order and a map that allows for quicker acce
# Intuition
<!-- Describe your first thoughts on how to solve this problem. -->
Do every process as mentioned keeping a set which manages the priority status of the process in descending order and a map that allows for quicker access.
# Approach
<!-- Describe your approach to solving the problem. -->
As given in the question, every process will have 3 entries $priority$,$taskId$ and $userId$.

As mentioned in the question, higher the priority, greater the precedence and for same priority, higher taskId will be given preference.
Hence, the structure of the set will be such:- 
set<pair<int,pair<int,int>>,greater<pair<int,pair<int,int>>>> which will store {priority,{taskId,userId}} in descending order.

![Biweekly 147 B i.jpeg](https://assets.leetcode.com/users/images/b1f9b9a7-78af-44ad-bd95-a78360e6308b_1736016370.0490782.jpeg)


Additionally we will create a map that will store the taskId as key and {priority,userId} as values.
This is done for easier access during editing and deleting.

# TaskManager(vector<vector<int>>& tasks)

In this method, we are given a 2-D vector where every index of the vector contains {userId,taskId,priority} of a process that needs to be inserted into the Task Manager. 
So basically what we will do is re-structure the query and insert into the set, {priority,{taskId,userId}}.

For example, 
if tasks[0]={1,101,10}, we will insert {10,{101,1}} into the set.

![Biweekly 147 B ii.jpeg](https://assets.leetcode.com/users/images/180e3f02-9314-48d7-8ad1-9c52bbdcf20d_1736012016.9437568.jpeg)

Also, append to the map taskId->{priority,userId} to allow faster and easier access.

![Biweekly 147 B iii.jpeg](https://assets.leetcode.com/users/images/d8590e33-e4e5-4137-baf7-3a286ed644b9_1736012309.240531.jpeg)


# void add(int userId,int taskId,int priority)

Does the same things as above just for a single porcess.

# void edit(int taskId,int newPriority)

This re-writes the priority of a process already present in the Task Manager.

Now, one can understand the significance of the map. The map which treats the taskId as the primary key will help us to easily find the data entry present in the set, delete it and enter the updated data entry.  

```
int prev=mp[taskId].first;
int userId=mp[taskId].second;
```
$prev$ stores the previous priority of the process with given $taskId$.
$userId$ stores the userId of the process with given $taskId$.

```
pq.erase({prev,{taskId,userId}});
mp[taskId].first=newPriority;
```
The first line deletes the entry {prev,{taskId,userId}}.
The second line re-writes the value of the key $taskId$ with {newPriority,userId}.

```
pq.insert({newPriority,{taskId,userId}});
```
The new entry is entered into the set.

# void rmv(int taskId)

```
int prrty=mp[taskId].first;
int userId=mp[taskId].second;
```
The above lines find the associated details of the given $taskId$ from the map.

```
pq.erase({prrty,{taskId,userId}});
mp.erase(taskId);
```
These two lines remove the details as they will no longer stay in the TaskManager. 

# int execTop()

This process basically executes the top priority process i.e. removes the top process from the TaskManager.

If the TaskManager is empty, return -1.
```
auto node=*pq.begin();
```
This stores the value of the first(highest priority) entry in the set which is of the following structure {priority,{taskId,userId}}.
```
mp.erase(node.second.first);
pq.erase(pq.begin());
```
Since $taskId$ of the process is the key, we will be erasing it from the map.
Also, we will erase the whole data entry itself from the set.
```
return node.second.second;
```
This return the $userId$ of the process that just got terminated.

# Dry Run

["TaskManager", "add", "edit", "execTop", "rmv", "add", "execTop"]
[[[[1, 101, 10], [2, 102, 20], [3, 103, 15]]], [4, 104, 5], [102, 8], [], [101], [5, 105, 15], []]

TaskManager([[[1, 101, 10], [2, 102, 20], [3, 103, 15]])

![WhatsApp Image 2025-01-04 at 23.45.54.jpeg](https://assets.leetcode.com/users/images/56e2adb4-3770-47d8-ac70-79d1162dd601_1736014579.311957.jpeg)


add([4, 104, 5])

![WhatsApp Image 2025-01-04 at 23.48.22.jpeg](https://assets.leetcode.com/users/images/4c025f3e-8a16-4134-bc40-9804a4791316_1736014723.0078743.jpeg)


edit([102, 8])

![WhatsApp Image 2025-01-05 at 00.07.00.jpeg](https://assets.leetcode.com/users/images/e910df3a-f13e-4d01-87fa-49a73ee544d7_1736015844.8436608.jpeg)

![WhatsApp Image 2025-01-05 at 00.08.27.jpeg](https://assets.leetcode.com/users/images/275f0dd6-79bd-4c04-9359-8c8fde91c745_1736015942.375032.jpeg)


execTop()

![WhatsApp Image 2025-01-05 at 00.10.11.jpeg](https://assets.leetcode.com/users/images/9bb7f089-47f2-4ac1-8fa0-8d90f8c00b03_1736016044.9821055.jpeg)


rmv(101)

![WhatsApp Image 2025-01-05 at 00.11.14.jpeg](https://assets.leetcode.com/users/images/2626a7bc-62e7-4f7c-b8a5-e56770fc6f49_1736016098.0973067.jpeg)

add([5, 105, 15])

![WhatsApp Image 2025-01-05 at 00.12.34.jpeg](https://assets.leetcode.com/users/images/15d03b4d-c7c2-440c-8edb-7da96c45bb2e_1736016172.8641582.jpeg)


execTop()

![WhatsApp Image 2025-01-05 at 00.13.22.jpeg](https://assets.leetcode.com/users/images/ea87d884-9100-4bcc-a777-8c3b04c46ae7_1736016283.3300145.jpeg)


# Complexity
- Time complexity:
    - TaskManager():- O(n log n) n:- size of vector
    - add():- O(log n)
    - edit():- O(log n)
    - rmv():- O(log n)
    - execTop():- O(log n)
<!-- Add your time complexity here, e.g. $$O(n)$$ -->

- Space complexity:- O(n)+O(n) [Set + Unordered Map]
<!-- Add your space complexity here, e.g. $$O(n)$$ -->

# Code
```cpp []
class TaskManager {
public:
    set<pair<int,pair<int,int>>,greater<pair<int,pair<int,int>>>>pq;
    unordered_map<int,pair<int,int>>mp;
    TaskManager(vector<vector<int>>& tasks) {
        for(auto it:tasks)
        {
            pq.insert({it[2],{it[1],it[0]}});
            mp[it[1]]={it[2],it[0]};
        }
    }
    
    void add(int userId, int taskId, int priority) {
        mp[taskId]={priority,userId};
        pq.insert({priority,{taskId,userId}});
    }
    
    void edit(int taskId, int newPriority) {
        int prev=mp[taskId].first;
        int userId=mp[taskId].second;
        pq.erase({prev,{taskId,userId}});
        mp[taskId].first=newPriority;
        pq.insert({newPriority,{taskId,userId}});
    }
    
    void rmv(int taskId) {
        int prrty=mp[taskId].first;
        int userId=mp[taskId].second;
        pq.erase({prrty,{taskId,userId}});
        mp.erase(taskId);
    }
    
    int execTop() {
        if(pq.empty())
            return -1;
        auto node=*pq.begin();
        mp.erase(node.second.first);
        pq.erase(pq.begin());
        return node.second.second;
    }
};

/**
 * 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();
 */
```
['Hash Table', 'Design', 'Ordered Map', 'Heap (Priority Queue)', 'C++']