#include <bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
using pll = pair<long long, long long>;
using pdb = pair<double, double>;
const int maxn = 1000010;
inline int get_num() {
  int now = 0;
  char ch = getchar();
  while (!isdigit(ch)) ch = getchar();
  while (isdigit(ch)) {
    now = (now << 1) + (now << 3) + ch - '0';
    ch = getchar();
  }
  return now;
}
inline char get_opt() {
  char ch = getchar();
  while (ch != '+' && ch != '-' && ch != '?') ch = getchar();
  return ch;
}
long long lazy[maxn << 2];
struct Node {
  int l, r;
  long long sum, val;
} t[maxn << 2];
inline void buildtree(int x, int l, int r) {
  t[x].l = l, t[x].r = r;
  if (l == r) return;
  int mid = (l + r) >> 1;
  buildtree(x << 1, l, mid);
  buildtree(x << 1 | 1, mid + 1, r);
}
inline void pushdown(int x) {
  lazy[x << 1] += lazy[x], lazy[x << 1 | 1] += lazy[x];
  t[x << 1].sum += lazy[x], t[x << 1 | 1].sum += lazy[x];
  t[x << 1].val += lazy[x], t[x << 1 | 1].val += lazy[x];
  lazy[x] = 0;
}
inline void changesum(int x, int l, int r, long long k) {
  if (t[x].l == l && t[x].r == r) {
    t[x].sum += k, t[x].val += k, lazy[x] += k;
    return;
  }
  if (lazy[x]) pushdown(x);
  int mid = (t[x].l + t[x].r) >> 1;
  if (r <= mid)
    changesum(x << 1, l, r, k);
  else if (l > mid)
    changesum(x << 1 | 1, l, r, k);
  else
    changesum(x << 1, l, mid, k), changesum(x << 1 | 1, mid + 1, r, k);
  t[x].val = max(t[x << 1].val, t[x << 1 | 1].val);
}
inline void changeval(int x, int pos, long long k) {
  if (t[x].l == t[x].r) {
    t[x].val += k;
    return;
  }
  if (lazy[x]) pushdown(x);
  int mid = (t[x].l + t[x].r) >> 1;
  if (pos <= mid)
    changeval(x << 1, pos, k);
  else
    changeval(x << 1 | 1, pos, k);
  t[x].val = max(t[x << 1].val, t[x << 1 | 1].val);
}
inline long long querysum(int x, int pos) {
  if (t[x].l == t[x].r) return t[x].sum;
  if (lazy[x]) pushdown(x);
  int mid = (t[x].l + t[x].r) >> 1;
  if (pos <= mid)
    return querysum(x << 1, pos);
  else
    return querysum(x << 1 | 1, pos);
}
inline long long queryval(int x, int pos) {
  if (t[x].r <= pos) return t[x].val;
  if (lazy[x]) pushdown(x);
  int mid = (t[x].l + t[x].r) >> 1;
  if (pos <= mid)
    return queryval(x << 1, pos);
  else
    return max(t[x << 1].val, queryval(x << 1 | 1, pos));
}
int pos[maxn], val[maxn];
int main() {
  const int L = 1, R = 1e6 + 5;
  buildtree(1, L, R);
  int q = get_num();
  for (int cas = 1; cas <= q; ++cas) {
    char opt = get_opt();
    if (opt == '+') {
      int x = get_num(), y = get_num();
      pos[cas] = x, val[cas] = y;
      changesum(1, x + 1, R, -y);
      changeval(1, x, x);
    } else if (opt == '-') {
      int x = get_num();
      changesum(1, pos[x] + 1, R, val[x]);
      changeval(1, pos[x], -pos[x]);
    } else {
      int x = get_num();
      long long tm = queryval(1, x) - querysum(1, x + 1);
      printf("%lld\n", max(tm - x, 0LL));
    }
  }
  return 0;
}
