Design Task Manager | Hashmap | Priority Queue✅ | C++ | Beginner friendly💯
Complexity

Time complexity:  Constructor: O(n log n)
add: O(log n)
edit: O(m + log n)
rmv: O(m)
execTop: O(n log n)


Space complexity: Constructor: O(n)
add:

# Complexity
- Time complexity:  Constructor: O(n log n)
                    add: O(log n)
                    edit: O(m + log n)
                    rmv: O(m)
                    execTop: O(n log n)
 



- Space complexity: Constructor: O(n)
                    add: O(n)
                    edit: O(n)
                    rmv: O(n)
                    execTop: O(n)


# Code
```cpp []
#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>
using namespace std;

class TaskManager {
private:
    unordered_map<int, pair<int, int>> taskMap;           // taskId -> {userId, priority}
    unordered_map<int, vector<pair<int, int>>> userTasks; // userId -> list of {taskId, priority}
    priority_queue<pair<int, pair<int, int>>> pq;         // max-heap: {priority, {taskId, userId}}

public:
    TaskManager(vector<vector<int>>& tasks) {
        for (const auto& task : tasks) {
            int userId = task[0];
            int taskId = task[1];
            int priority = task[2];

            taskMap[taskId] = {userId, priority};
            userTasks[userId].push_back({taskId, priority});
            pq.push({priority, {taskId, userId}});
        }
    }

    void add(int userId, int taskId, int priority) {
        taskMap[taskId] = {userId, priority};
        userTasks[userId].push_back({taskId, priority});
        pq.push({priority, {taskId, userId}});
    }

    void edit(int taskId, int newPriority) {
        auto [userId, oldPriority] = taskMap[taskId];
        taskMap[taskId].second = newPriority;

        // Update userTasks
        auto& tasks = userTasks[userId];
        for (auto& task : tasks) {
            if (task.first == taskId) {
                task.second = newPriority;
                break;
            }
        }

        // Add the updated task to the priority queue
        pq.push({newPriority, {taskId, userId}});
    }

    void rmv(int taskId) {
        auto [userId, priority] = taskMap[taskId];
        taskMap.erase(taskId);

        auto& tasks = userTasks[userId];
        for (auto it = tasks.begin(); it != tasks.end(); ++it) {
            if (it->first == taskId) {
                tasks.erase(it);
                break;
            }
        }
    }

    int execTop() {
        while (!pq.empty()) {
            auto [priority, taskInfo] = pq.top();
            int taskId = taskInfo.first;
            int userId = taskInfo.second;
            pq.pop();

            // Check if the task is still valid
            if (taskMap.find(taskId) != taskMap.end() && taskMap[taskId].second == priority) {
                rmv(taskId); // Remove the task from the system
                return userId;
            }
        }
        return -1; // If no valid tasks are available
    }
};

```
['C++']