#include <bits/stdc++.h>
using namespace std;
namespace node_tre {
int tre[100005] = {};
void update(int x, int val) { tre[x] += val; }
int ask(int x) { return tre[x]; }
void cover(int x) { tre[x] = 0; }
};  // namespace node_tre
using namespace node_tre;
struct node {
  int ty;
  int id;
  int tim;
  int val;
  int w;
} a[100005], b[100005];
int n;
int ans[100005];
int cnt;
map<int, int> has;
void cdq(int l, int r) {
  if (r == l) return;
  int mid = (l + r) >> 1;
  cdq(l, mid);
  cdq(mid + 1, r);
  int indl = l, indr = mid + 1, indb = l;
  while (indl <= mid && indr <= r) {
    if (a[indl].tim <= a[indr].tim) {
      if (a[indl].ty == 1) update(a[indl].val, a[indl].w);
      b[indb++] = a[indl++];
    } else {
      if (a[indr].ty == 2) ans[a[indr].id] += ask(a[indr].val);
      b[indb++] = a[indr++];
    }
  }
  while (indl <= mid) b[indb++] = a[indl++];
  while (indr <= r) {
    if (a[indr].ty == 2) ans[a[indr].id] += ask(a[indr].val);
    b[indb++] = a[indr++];
  }
  for (int i = l; i <= r; i++) {
    a[i] = b[i];
    cover(a[i].val);
  }
}
int main() {
  memset(ans, -1, sizeof(ans));
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a[i].ty >> a[i].tim >> a[i].val;
    a[i].id = i;
    if (a[i].ty == 1) {
      a[i].w = 1;
      continue;
    }
    if (a[i].ty == 2) {
      a[i].ty = 1;
      a[i].w = -1;
      continue;
    }
    if (a[i].ty == 3) {
      ans[i] = 0;
      a[i].ty = 2;
      continue;
    }
  }
  for (int i = 1; i <= n; i++) {
    if (has[a[i].val] == 0) has[a[i].val] = ++cnt;
    a[i].val = has[a[i].val];
  }
  cdq(1, n);
  for (int i = 1; i <= n; i++)
    if (ans[i] != -1) cout << ans[i] << '\n';
  return 0;
}
