#include <bits/stdc++.h>
using namespace std;
typedef struct node {
  int val, prior, size;
  struct node *l, *r;
} node;
typedef node *pnode;
int sz(pnode t) { return t ? t->size : 0; }
void upd_sz(pnode t) {
  if (t) t->size = sz(t->l) + 1 + sz(t->r);
}
void split(pnode t, pnode &l, pnode &r, int key) {
  if (!t)
    l = r = NULL;
  else if (t->val <= key)
    split(t->r, t->r, r, key), l = t;
  else
    split(t->l, l, t->l, key), r = t;
  upd_sz(t);
}
void merge(pnode &t, pnode l, pnode r) {
  if (!l || !r)
    t = l ? l : r;
  else if (l->prior > r->prior)
    merge(l->r, l->r, r), t = l;
  else
    merge(r->l, l, r->l), t = r;
  upd_sz(t);
}
void insert(pnode &t, pnode it) {
  if (!t)
    t = it;
  else if (it->prior > t->prior)
    split(t, it->l, it->r, it->val), t = it;
  else
    insert(t->val < it->val ? t->r : t->l, it);
  upd_sz(t);
}
void erase(pnode &t, int key) {
  if (!t)
    return;
  else if (t->val == key) {
    pnode temp = t;
    merge(t, t->l, t->r);
    free(temp);
  } else
    erase(t->val < key ? t->r : t->l, key);
  upd_sz(t);
}
pnode init(int val) {
  pnode ret = (pnode)malloc(sizeof(node));
  ret->val = val;
  ret->size = 1;
  ret->prior = rand();
  ret->l = ret->r = NULL;
  return ret;
}
int query(pnode node, int k) {
  if (!node) return 0;
  if (node->val > k)
    return query(node->l, k);
  else
    return sz(node->l) + 1 + query(node->r, k);
}
pnode tree[2][100001];
int val[100001], type[100001], tme[100001];
map<int, int> assign;
vector<int> v;
int main() {
  ios::sync_with_stdio(false);
  ;
  cin.tie(0);
  ;
  int i, j, n, x, y, ctr;
  for (i = 0; i < 100001; i++) {
    tree[0][i] = NULL;
    tree[1][i] = NULL;
  }
  cin >> n;
  for (i = 1; i <= n; i++) {
    cin >> type[i] >> tme[i] >> val[i];
    v.push_back(val[i]);
  }
  ctr = 0;
  sort(v.begin(), v.end());
  for (i = 0; i < v.size(); i++) {
    if (!assign[v[i]]) {
      ctr++;
      assign[v[i]] = ctr;
    }
  }
  for (i = 1; i <= n; i++) val[i] = assign[val[i]];
  for (i = 1; i <= n; i++) {
    if (type[i] == 1)
      insert(tree[0][val[i]], init(tme[i]));
    else if (type[i] == 2)
      insert(tree[1][val[i]], init(tme[i]));
    else
      cout << query(tree[0][val[i]], tme[i]) - query(tree[1][val[i]], tme[i])
           << "\n";
  }
  return 0;
}
