My Solutions
1. Use the std::list2. Use the std::shared_ptr
**1. Use the `std::list`**
```
/**
 * Space Complexity: O(n)
 * where `n` is the number of the tasks in the class `TaskManager`
 */
class TaskManager {
 private:
  /**
   * <0>: the user id
   * <1>: the task id
   * <2>: the priority of the task
   * <3>: the flag indicating whether the task has been removed
   */
  using task_t = tuple<int, int, int, bool>;
  static constexpr int user_id_i = 0;
  static constexpr int task_id_i = 1;
  static constexpr int priority_i = 2;
  static constexpr int removed_i = 3;
  
  using tasks_t = list<task_t>;
  using task_itr_t = tasks_t::iterator;
  
  class TaskCompare {
   public:
    bool operator()(const task_itr_t &lhs, const task_itr_t &rhs) const noexcept {
      return !(
        get<priority_i>(*lhs) > get<priority_i>(*rhs) ||
        (get<priority_i>(*lhs) == get<priority_i>(*rhs) && get<task_id_i>(*lhs) > get<task_id_i>(*rhs))
      );
    }
  };
  
  using task_pq_t = priority_queue<task_itr_t, vector<task_itr_t>, TaskCompare>;
  using task_map_t = unordered_map<int, task_itr_t>;
  
 public:
  /**
   * Time Complexity: O(n * log(n))
   * Space Complexity: O(1)
   * where `n` is the length of the vector `tasks`
   */
  TaskManager(const vector<vector<int>> &tasks) {
    for (const vector<int> &task : tasks) {
      add(task[user_id_i], task[task_id_i], task[priority_i]);
    }
  }
  
  /**
   * Time Complexity: O(log(n))
   * Space Complexity: O(1)
   * where `n` is the length of the priority_queue `task_pq_`
   */
  void add(const int userId, const int taskId, const int priority) {
    tasks_.emplace_front(userId, taskId, priority, false);
    task_itr_t itr = tasks_.begin();
    task_pq_.emplace(itr);
    task_map_[taskId] = itr;
  }
  
  /**
   * Time Complexity: O(log(n))
   * Space Complexity: O(1)
   * where `n` is the length of the priority_queue `task_pq_`
   */
  void edit(const int taskId, const int newPriority) {
    task_itr_t itr_removed = remove(taskId);
    add(get<user_id_i>(*itr_removed), taskId, newPriority);
  }
  
  /**
   * Time Complexity: O(1)
   * Space Complexity: O(1)
   */
  void rmv(const int taskId) {
    remove(taskId);
  }
  
  /**
   * Time Complexity: O(log(n))
   * Space Complexity: O(1)
   * where `n` is the length of the priority_queue `task_pq_`
   */
  int execTop() {
    constexpr int no_task = -1;
    while (!task_pq_.empty() && get<removed_i>(*task_pq_.top())) {
      auto itr = task_pq_.top();
      tasks_.erase(itr);
      task_pq_.pop();
    }
    if (task_pq_.empty()) {
      return no_task;
    }
    
    auto itr = task_pq_.top();
    task_pq_.pop();
    task_map_.erase(get<task_id_i>(*itr));
    const int ret = get<user_id_i>(*itr);
    tasks_.erase(itr);
    return ret;
  }
  
 private:
  task_itr_t remove(const int task_id) {
    auto itr = task_map_.find(task_id);
    task_itr_t ret = itr->second;
    get<removed_i>(*ret) = true;
    task_map_.erase(itr);
    return ret;
  }
  
  tasks_t tasks_;
  task_pq_t task_pq_;
  task_map_t task_map_;
};
```
**2. Use the `std::shared_ptr`**
```
/**
 * Space Complexity: O(n)
 * where `n` is the number of the tasks in the class `TaskManager`
 */
class TaskManager {
 private:
  /**
   * <0>: the user id
   * <1>: the task id
   * <2>: the priority of the task
   * <3>: the flag indicating whether the task has been removed
   */
  using task_t = tuple<int, int, int, bool>;
  static constexpr int user_id_i = 0;
  static constexpr int task_id_i = 1;
  static constexpr int priority_i = 2;
  static constexpr int removed_i = 3;

  using task_ptr_t = shared_ptr<task_t>;
  
  class TaskCompare {
   public:
    bool operator()(const task_ptr_t &lhs, const task_ptr_t &rhs) const noexcept {
      return !(
        get<priority_i>(*lhs) > get<priority_i>(*rhs) ||
        (get<priority_i>(*lhs) == get<priority_i>(*rhs) && get<task_id_i>(*lhs) > get<task_id_i>(*rhs))
      );
    }
  };
  
  using task_pq_t = priority_queue<task_ptr_t, vector<task_ptr_t>, TaskCompare>;
  using task_map_t = unordered_map<int, task_ptr_t>;
  
 public:
  /**
   * Time Complexity: O(n * log(n))
   * Space Complexity: O(1)
   * where `n` is the length of the vector `tasks`
   */
  TaskManager(const vector<vector<int>> &tasks) {
    for (const vector<int> &task : tasks) {
      add(task[user_id_i], task[task_id_i], task[priority_i]);
    }
  }
  
  /**
   * Time Complexity: O(log(n))
   * Space Complexity: O(1)
   * where `n` is the length of the priority_queue `task_pq_`
   */
  void add(const int userId, const int taskId, const int priority) {
    task_ptr_t task = make_shared<task_t>(userId, taskId, priority, false);
    task_map_[taskId] = task;
    task_pq_.emplace(move(task));
  }
  
  /**
   * Time Complexity: O(log(n))
   * Space Complexity: O(1)
   * where `n` is the length of the priority_queue `task_pq_`
   */
  void edit(const int taskId, const int newPriority) {
    task_ptr_t removed = remove(taskId);
    add(get<user_id_i>(*removed), taskId, newPriority);
  }
  
  /**
   * Time Complexity: O(1)
   * Space Complexity: O(1)
   */
  void rmv(const int taskId) {
    remove(taskId);
  }
  
  /**
   * Time Complexity: O(log(n))
   * Space Complexity: O(1)
   * where `n` is the length of the priority_queue `task_pq_`
   */
  int execTop() {
    constexpr int no_task = -1;
    while (!task_pq_.empty() && get<removed_i>(*task_pq_.top())) {
      task_pq_.pop();
    }
    if (task_pq_.empty()) {
      return no_task;
    }
    
    task_ptr_t task = task_pq_.top();
    task_pq_.pop();
    task_map_.erase(get<task_id_i>(*task));
    return get<user_id_i>(*task);
  }
  
 private:
  task_ptr_t remove(const int task_id) {
    auto itr = task_map_.find(task_id);
    task_ptr_t ret = itr->second;
    get<removed_i>(*ret) = true;
    task_map_.erase(itr);
    return ret;
  }
  
  task_pq_t task_pq_;
  task_map_t task_map_;
};
```
['C++']