#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
struct point {
  int flag;
  int time;
  int num;
} p[maxn];
int refer[maxn];
struct node {
  int l, r;
  map<int, int> mp;
} a[maxn << 4];
void init(int i, int l, int r) {
  a[i].l = l;
  a[i].r = r;
  a[i].mp.clear();
  if (l != r) {
    int mid = (l + r) / 2;
    init(2 * i, l, mid);
    init(2 * i + 1, mid + 1, r);
  }
}
void insert1(int i, int pos, int num) {
  int l = a[i].l, r = a[i].r;
  a[i].mp[num]++;
  if (l == r) return;
  int mid = (l + r) / 2;
  if (pos <= mid)
    insert1(2 * i, pos, num);
  else
    insert1(2 * i + 1, pos, num);
}
void insert2(int i, int pos, int num) {
  int l = a[i].l, r = a[i].r;
  a[i].mp[num]--;
  if (l == r) return;
  int mid = (l + r) / 2;
  if (pos <= mid)
    insert2(2 * i, pos, num);
  else
    insert2(2 * i + 1, pos, num);
}
int find(int i, int x, int y, int num) {
  int l = a[i].l, r = a[i].r;
  if (l == x && r == y) return a[i].mp[num];
  int mid = (l + r) / 2;
  if (y <= mid)
    return find(2 * i, x, y, num);
  else if (x >= mid + 1)
    return find(2 * i + 1, x, y, num);
  else
    return find(2 * i, x, mid, num) + find(2 * i + 1, mid + 1, y, num);
}
int main() {
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n; i++)
    scanf("%d%d%d", &p[i].flag, &p[i].time, &p[i].num);
  for (int i = 0; i < n; i++) refer[i] = p[i].time;
  sort(refer, refer + n);
  for (int i = 0; i < n; i++)
    p[i].time = upper_bound(refer, refer + n, p[i].time) - refer;
  init(1, 1, n);
  for (int i = 0; i < n; i++) {
    int flag = p[i].flag;
    int time = p[i].time;
    int num = p[i].num;
    if (flag == 1)
      insert1(1, time, num);
    else if (flag == 2)
      insert2(1, time, num);
    else
      printf("%d\n", find(1, 1, time, num));
  }
  return 0;
}
