#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
const int mx = 105;
const int mod = 1e9 + 5;
const long long inf = 34359738370;
const int INF = 1e9 + 5;
int tree1[maxn * mx], lc1[maxn * mx], rc1[maxn * mx], root1[maxn], tot1 = 0;
int tree2[maxn * mx], lc2[maxn * mx], rc2[maxn * mx], root2[maxn], tot2 = 0;
map<string, int> mp;
string s1, s2;
int n, t, cnt = 0;
void updata1(int &rt, int last, int l, int r, int pos, int v) {
  rt = ++tot1;
  tree1[rt] = tree1[last] + v;
  lc1[rt] = lc1[last], rc1[rt] = rc1[last];
  if (l == r) return;
  int mid = (l + r) >> 1;
  if (pos <= mid)
    updata1(lc1[rt], lc1[last], l, mid, pos, v);
  else
    updata1(rc1[rt], rc1[last], mid + 1, r, pos, v);
}
int query1(int rt, int l, int r, int vl, int vr) {
  if (vl <= l && r <= vr) return tree1[rt];
  int mid = (l + r) >> 1;
  if (vl > mid)
    return query1(rc1[rt], mid + 1, r, vl, vr);
  else if (vr <= mid)
    return query1(lc1[rt], l, mid, vl, vr);
  return query1(lc1[rt], l, mid, vl, vr) + query1(rc1[rt], mid + 1, r, vl, vr);
}
int query2(int rt, int l, int r, int pos) {
  if (l == r) return tree2[rt];
  int mid = (l + r) >> 1;
  if (pos <= mid)
    return query2(lc2[rt], l, mid, pos);
  else
    return query2(rc2[rt], mid + 1, r, pos);
}
void updata2(int &rt, int last, int l, int r, int pos, int v) {
  rt = ++tot2;
  lc2[rt] = lc2[last], rc2[rt] = rc2[last];
  if (l == r) {
    tree2[rt] = v;
    return;
  }
  int mid = (l + r) >> 1;
  if (pos <= mid)
    updata2(lc2[rt], lc2[last], l, mid, pos, v);
  else
    updata2(rc2[rt], rc2[last], mid + 1, r, pos, v);
}
int main() {
  cin >> n;
  for (int i = 1; i <= n; i++) {
    root1[i] = root1[i - 1];
    root2[i] = root2[i - 1];
    cin >> s1;
    if (s1[0] == 's') {
      cin >> s2 >> t;
      if (!mp[s2]) mp[s2] = ++cnt;
      int flag1 = mp[s2];
      int flag2 = query2(root2[i], 1, maxn, flag1);
      if (!flag2) {
        updata2(root2[i], root2[i - 1], 1, maxn, flag1, t);
        updata1(root1[i], root1[i - 1], 1, INF, t, 1);
      } else {
        int temp;
        updata1(temp, root1[i - 1], 1, INF, flag2, -1);
        updata1(root1[i], temp, 1, INF, t, 1);
        updata2(root2[i], root2[i - 1], 1, maxn, flag1, t);
      }
    } else if (s1[0] == 'q') {
      cin >> s2;
      if (!mp[s2]) mp[s2] = ++cnt;
      int t = mp[s2];
      int s = query2(root2[i], 1, maxn, t);
      if (!s) {
        cout << -1 << '\n';
        continue;
      } else if (s == 1) {
        cout << 0 << '\n';
        continue;
      }
      cout << query1(root1[i], 1, INF, 1, s - 1) << '\n';
    } else if (s1[0] == 'r') {
      cin >> s2;
      if (!mp[s2]) mp[s2] = ++cnt;
      int t = mp[s2];
      int flag2 = query2(root2[i], 1, maxn, t);
      if (!flag2) continue;
      updata1(root1[i], root1[i - 1], 1, INF, flag2, -1);
      updata2(root2[i], root2[i - 1], 1, maxn, t, 0);
    } else if (s1[0] == 'u') {
      cin >> t;
      root1[i] = root1[i - 1 - t];
      root2[i] = root2[i - 1 - t];
    }
  }
  return 0;
}
