#include <bits/stdc++.h>
class SegmentTree {
 public:
  void Build(const int64_t size) {
    size_ = size;
    tree_.resize(size_ * 4);
    Init(1, 0, size_ - 1);
  }
  int64_t CountWaitTime(const int64_t& pos) {
    wait_time_ = 0;
    CalcSum(1, 0, size_ - 1, pos);
    return wait_time_;
  }
  void Add(const int64_t& pos, const int64_t& value) {
    new_value_ = value;
    UpdateNode(1, 0, size_ - 1, pos);
  }
  void Remove(const int64_t& pos, const int64_t& value) {
    new_value_ = -value;
    UpdateNode(1, 0, size_ - 1, pos);
  }

 private:
  void CalcSum(int64_t node_id, int64_t left, int64_t right, int64_t pos) {
    if (right <= pos) {
      wait_time_ = std::max(wait_time_ + tree_.at(node_id).total_wait,
                            tree_.at(node_id).max_wait);
      return;
    }
    int64_t middle = (left + right) / 2;
    CalcSum(node_id * 2, left, middle, pos);
    if (middle < pos) {
      CalcSum(node_id * 2 + 1, middle + 1, right, pos);
    }
  }
  void UpdateNode(int64_t node_id, int64_t left, int64_t right, int64_t pos) {
    if (left == right) {
      tree_.at(node_id).SetValue(new_value_, new_value_);
    } else {
      int64_t middle = (left + right) / 2;
      if (pos <= middle) {
        UpdateNode(node_id * 2, left, middle, pos);
      } else {
        UpdateNode(node_id * 2 + 1, middle + 1, right, pos);
      }
      tree_.at(node_id).Merge(tree_.at(node_id * 2), tree_.at(node_id * 2 + 1));
    }
  }
  void Init(int64_t node_id, int64_t left, int64_t right) {
    if (left == right) {
      tree_.at(node_id).SetValue(0, left);
      return;
    }
    int64_t middle = (left + right) / 2;
    Init(node_id * 2, left, middle);
    Init(node_id * 2 + 1, middle + 1, right);
    tree_.at(node_id).Merge(tree_[node_id * 2], tree_[node_id * 2 + 1]);
  }
  struct Node {
   public:
    void SetValue(const int64_t& total, const int64_t& max) {
      total_wait += total;
      max_wait += max;
    }
    void Merge(const Node& lhs, const Node& rhs) {
      total_wait = lhs.total_wait + rhs.total_wait;
      max_wait = std::max(lhs.max_wait + rhs.total_wait, rhs.max_wait);
    }
    int64_t total_wait{};
    int64_t max_wait{};
  };
  int64_t size_{};
  int64_t wait_time_{};
  int64_t new_value_{};
  std::vector<Node> tree_;
};
int main() {
  int64_t num_of_queries{};
  std::cin >> num_of_queries;
  SegmentTree reception_queue;
  reception_queue.Build(1e6);
  int64_t min_wait{0};
  int64_t diff{};
  char flag{};
  std::vector<std::pair<int64_t, int64_t>> queue;
  queue.resize(num_of_queries);
  std::vector<int64_t> ans;
  ans.reserve(num_of_queries);
  for (int64_t i = 0, time{}, duration{}; i < num_of_queries; i++) {
    std::cin.ignore();
    std::cin >> flag >> time;
    switch (flag) {
      case '?':
        diff = reception_queue.CountWaitTime(time) - time;
        ans.push_back(std::max(min_wait, diff));
        break;
      case '+':
        std::cin >> duration;
        reception_queue.Add(time, duration);
        queue.at(i) = {time, duration};
        break;
      case '-':
        reception_queue.Remove(queue.at(time - 1).first,
                               queue.at(time - 1).second);
    }
  }
  for (const auto& elem : ans) {
    std::cout << elem << "\n";
  }
  return 0;
}
