#include <bits/stdc++.h>
using namespace std;
struct QUERY {
  int query, time, number;
};
void update(vector<map<int, int> > &tree, int v, int tl, int tr, int pos,
            int query, int value) {
  if (pos < tl || pos > tr) return;
  if (query == 1)
    tree[v][value]++;
  else if (query == 2)
    tree[v][value]--;
  if (tr != tl) {
    update(tree, 2 * v, tl, (tr + tl) / 2, pos, query, value);
    update(tree, 2 * v + 1, (tr + tl) / 2 + 1, tr, pos, query, value);
  }
}
int sum(vector<map<int, int> > &tree, int v, int tl, int tr, int i, int j,
        int value) {
  if (i > tr || j < tl) return 0;
  if (i <= tl && j >= tr) return tree[v][value];
  int sum1 = sum(tree, 2 * v, tl, (tr + tl) / 2, i, j, value);
  int sum2 = sum(tree, 2 * v + 1, (tr + tl) / 2 + 1, tr, i, j, value);
  return sum1 + sum2;
}
int main() {
  int n;
  cin >> n;
  vector<QUERY> a(n + 1);
  vector<int> num(n + 1);
  vector<int> t(n + 1);
  for (int i = 1; i <= n; ++i) {
    cin >> a[i].query >> a[i].time >> a[i].number;
    num[i] = a[i].number;
    t[i] = a[i].time;
  }
  sort(num.begin(), num.end());
  num.erase(unique(num.begin(), num.end()), num.end());
  sort(t.begin(), t.end());
  t.erase(unique(t.begin(), t.end()), t.end());
  map<int, int> help;
  for (unsigned int i = 1; i < num.size(); ++i) {
    help.insert(make_pair(num[i], i));
  }
  for (int i = 1; i <= n; ++i) {
    a[i].number = help[a[i].number];
  }
  help.clear();
  for (unsigned int i = 1; i < t.size(); ++i) {
    help.insert(make_pair(t[i], i));
  }
  for (int i = 1; i <= n; ++i) {
    a[i].time = help[a[i].time];
  }
  int len = t.size() - 1;
  int tree_size = 4 * len;
  vector<map<int, int> > tree(tree_size);
  for (int i = 1; i <= n; ++i) {
    if (a[i].query != 3)
      update(tree, 1, 1, len, a[i].time, a[i].query, a[i].number);
    else
      cout << sum(tree, 1, 1, len, 1, a[i].time, a[i].number) << endl;
  }
  return 0;
}
