#include <bits/stdc++.h>
using namespace std;
const int Q = 1e5 + 10;
struct Trie {
  struct Node {
    int prio;
    Node *child[26];
    Node(int prio = 0) : prio(prio) {
      for (int i = 0; i < 26; i++) child[i] = NULL;
    }
  };
  int prio(Node *node) { return node ? node->prio : 0; }
  Node *child(Node *node, int i) { return node ? node->child[i] : NULL; }
  Node *modify(Node *node, char s[], int n, int i, int val) {
    Node *nxt = new Node(prio(node));
    for (int i = 0; i < 26; i++) nxt->child[i] = child(node, i);
    if (i == n) {
      nxt->prio = val;
    } else {
      nxt->child[s[i] - 'a'] =
          modify(child(node, s[i] - 'a'), s, n, i + 1, val);
    }
    return nxt;
  }
  int find(Node *node, char s[], int n, int i) {
    if (!node) return 0;
    if (i == n) return node->prio;
    return find(node->child[s[i] - 'a'], s, n, i + 1);
  }
} trie;
struct SegTree {
  struct Node {
    int qtd;
    Node *L, *R;
    Node(int qtd = 0) : qtd(qtd), L(NULL), R(NULL) {}
  };
  inline int qtd(Node *node) { return node ? node->qtd : 0; }
  inline Node *L(Node *node) { return node ? node->L : NULL; }
  inline Node *R(Node *node) { return node ? node->R : NULL; }
  Node *add(Node *node, int l, int r, int pos, int val) {
    Node *nxt = new Node(qtd(node) + val);
    if (l != r) {
      int mid = (l + r) / 2;
      if (pos <= mid) {
        nxt->L = add(L(node), l, mid, pos, val);
        nxt->R = R(node);
      } else {
        nxt->L = L(node);
        nxt->R = add(R(node), mid + 1, r, pos, val);
      }
    }
    return nxt;
  }
  int query(Node *node, int l, int r, int a, int b) {
    if (!node || l > b || r < a) return 0;
    if (l >= a && r <= b) return node->qtd;
    int mid = (l + r) / 2;
    return query(node->L, l, mid, a, b) + query(node->R, mid + 1, r, a, b);
  }
} segTree;
pair<Trie::Node *, SegTree::Node *> roots[Q];
int main() {
  int q;
  scanf("%d", &q);
  roots[0] = {new Trie::Node(), new SegTree::Node()};
  for (int k = 1; k <= q; k++) {
    char t[10];
    scanf("%s", t);
    roots[k] = roots[k - 1];
    if (strcmp(t, "set") == 0) {
      char a[20];
      int first;
      scanf("%s %d", a, &first);
      int prio = trie.find(roots[k].first, a, strlen(a), 0);
      if (prio)
        roots[k].second = segTree.add(roots[k].second, 1, 1e9, prio, -1);
      roots[k].first = trie.modify(roots[k].first, a, strlen(a), 0, first);
      roots[k].second = segTree.add(roots[k].second, 1, 1e9, first, 1);
    } else if (strcmp(t, "remove") == 0) {
      char a[20];
      scanf("%s", a);
      int prio = trie.find(roots[k].first, a, strlen(a), 0);
      if (prio) {
        roots[k].first = trie.modify(roots[k].first, a, strlen(a), 0, 0);
        roots[k].second = segTree.add(roots[k].second, 1, 1e9, prio, -1);
      }
    } else if (strcmp(t, "query") == 0) {
      char a[20];
      scanf("%s", a);
      int prio = trie.find(roots[k].first, a, strlen(a), 0);
      printf("%d\n",
             prio ? segTree.query(roots[k].second, 1, 1e9, 1, prio - 1) : -1);
      fflush(stdout);
    } else if (strcmp(t, "undo") == 0) {
      int d;
      scanf("%d", &d);
      roots[k] = roots[k - d - 1];
    }
  }
  return 0;
}
