#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 15;
struct Persistent {
  int l, r, s;
  Persistent() { l = r = s = 0; }
} t[N << 5];
int n, no, avail, root[N];
map<int, int> vis;
int squeeze(int x) {
  if (vis.find(x) == vis.end()) vis[x] = ++no;
  return vis[x];
}
int update(int pre, int b, int e, int pos, int v) {
  int node = ++avail;
  t[node] = t[pre];
  if (b == e) {
    t[node].s += v;
    return node;
  }
  int m = (b + e) >> 1;
  if (pos <= m)
    t[node].l = update(t[node].l, b, m, pos, v);
  else
    t[node].r = update(t[node].r, m + 1, e, pos, v);
  t[node].s = t[t[node].l].s + t[t[node].r].s;
  return node;
}
int query(int node, int b, int e, int l, int r) {
  if (e < l || b > r || b > e) return 0;
  if (l <= b && e <= r) return t[node].s;
  int m = (b + e) >> 1;
  return query(t[node].l, b, m, l, r) + query(t[node].r, m + 1, e, l, r);
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> n;
  for (int i = 1; i <= n; i += 1) {
    int operation, t, x;
    cin >> operation >> t >> x;
    x = squeeze(x);
    if (operation == 1) {
      root[x] = update(root[x], 1, 1e9, t, +1);
    } else if (operation == 2) {
      root[x] = update(root[x], 1, 1e9, t, -1);
    } else {
      cout << query(root[x], 1, 1e9, 1, t) << '\n';
    }
  }
  return 0;
}
