#include <bits/stdc++.h>
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
long long rand(long long l, long long r) {
  uniform_int_distribution<long long> uid(l, r);
  return uid(rng);
}
const int mod = 1e9 + 7;
int pwr(int a, int b) {
  int ans = 1;
  while (b) {
    if (b & 1) {
      ans = (ans * 1LL * a) % mod;
    }
    a = (a * 1LL * a) % mod;
    b >>= 1;
  }
  return ans;
}
const int N = 2e5 + 5;
const int NN = 1e7 + 5;
struct node {
  int l, r, val;
  node() { l = r = val = 0; }
} cache[NN];
int sz = 0;
int newNode() { return ++sz; }
map<string, int> names;
int version1[NN], version2[NN];
int qp1[N], qp2[N];
int cur1 = 0, cur2 = 0, tt = 0;
int q;
const int MAX = 1e9 + 7;
void upd1(int &r, int pr, int s, int e, int idx, int val) {
  if (!r) r = newNode();
  if (s == e) {
    cache[r].val = val;
    return;
  }
  int m = (s + e) >> 1;
  if (idx <= m) {
    upd1(cache[r].l, cache[pr].l, s, m, idx, val);
    cache[r].r = cache[pr].r;
  } else {
    upd1(cache[r].r, cache[pr].r, m + 1, e, idx, val);
    cache[r].l = cache[pr].l;
  }
}
void upd2(int &r, int pr, int s, int e, int idx, int val) {
  if (!r) r = newNode();
  cache[r].val = cache[pr].val + val;
  if (s == e) return;
  int m = (s + e) >> 1;
  if (idx <= m) {
    upd2(cache[r].l, cache[pr].l, s, m, idx, val);
    cache[r].r = cache[pr].r;
  } else {
    upd2(cache[r].r, cache[pr].r, m + 1, e, idx, val);
    cache[r].l = cache[pr].l;
  }
}
int query1(int r, int s, int e, int c) {
  if (!r) return 0;
  if (s == e) return cache[r].val;
  int m = (s + e) >> 1;
  if (c <= m)
    return query1(cache[r].l, s, m, c);
  else
    return query1(cache[r].r, m + 1, e, c);
}
int query2(int rr, int s, int e, int l, int r) {
  if (s > r || e < l || !rr) return 0;
  if (l <= s && e <= r) return cache[rr].val;
  int m = (s + e) >> 1;
  return query2(cache[rr].l, s, m, l, r) + query2(cache[rr].r, m + 1, e, l, r);
}
void upd1(int c, int x) {
  tt++;
  upd1(version1[tt], version1[cur1], 1, q, c, x);
  cur1 = tt;
}
void upd2(int c, int x) {
  tt++;
  upd2(version2[tt], version2[cur2], 1, MAX, c, x);
  cur2 = tt;
}
int query1(int c) { return query1(version1[cur1], 1, q, c); }
int query2(int l, int r) {
  if (l > r) return 0;
  return query2(version2[cur2], 1, MAX, l, r);
}
signed main() {
  ios_base::sync_with_stdio(0);
  cin >> q;
  int c = 0;
  for (int i = 1; i <= q; i++) {
    string type;
    cin >> type;
    if (type == "set") {
      string s;
      cin >> s;
      int x;
      cin >> x;
      if (!names.count(s)) {
        names[s] = ++c;
      }
      int k = names[s];
      int z = query1(k);
      if (!z) {
        upd1(k, x);
        upd2(x, 1);
      } else {
        upd1(k, x);
        upd2(z, -1);
        upd2(x, 1);
      }
    } else if (type == "remove") {
      string s;
      cin >> s;
      if (!names.count(s)) {
        names[s] = ++c;
      }
      int k = names[s];
      int z = query1(k);
      if (z) {
        upd1(k, 0);
        upd2(z, -1);
      }
    } else if (type == "query") {
      string s;
      cin >> s;
      if (!names.count(s)) {
        names[s] = ++c;
      }
      int k = names[s];
      int z = query1(k);
      if (z) {
        cout << query2(1, z - 1) << '\n';
      } else {
        cout << -1 << '\n';
      }
    } else {
      int d;
      cin >> d;
      cur1 = qp1[i - d - 1], cur2 = qp2[i - d - 1];
    }
    qp1[i] = cur1;
    qp2[i] = cur2;
  }
  return 0;
}
