#include <bits/stdc++.h>
using namespace std;
int Q;
int kuai = 400;
int tot;
int cnt;
int num;
map<int, int> mp;
map<int, int> shi;
struct node {
  int tim;
  int ge;
};
vector<node> v[100005];
int root[100005];
int lc[100005 * 100], rc[100005 * 100], sum[100005 * 100];
int modify(int x, int l, int r, int wh, int val) {
  if (!x) x = ++num;
  sum[x] += val;
  if (l == r) return x;
  int mid = (l + r) / 2;
  if (mid >= wh) {
    lc[x] = modify(lc[x], l, mid, wh, val);
  } else {
    rc[x] = modify(rc[x], mid + 1, r, wh, val);
  }
  return x;
}
int query(int x, int l, int r, int tx, int ty) {
  if (!x) return 0;
  if (l >= tx && r <= ty) return sum[x];
  int mid = (l + r) / 2;
  int ret = 0;
  if (mid >= tx) ret += query(lc[x], l, mid, tx, ty);
  if (mid < ty) ret += query(rc[x], mid + 1, r, tx, ty);
  return ret;
}
void jia(int x, int tim) { root[x] = modify(root[x], 1, 1000000000, tim, 1); }
void clear(int x, int tim) {
  root[x] = modify(root[x], 1, 1000000000, tim, -1);
}
int xunwen(int x, int tim) { return query(root[x], 1, 1000000000, 1, tim); }
void build(int x) {
  shi[x] = ++cnt;
  root[cnt] = ++num;
  for (int i = 0; i < (int)v[x].size(); i++) {
    root[cnt] = modify(root[cnt], 1, 1000000000, v[x][i].tim, v[x][i].ge);
  }
}
int main() {
  scanf("%d", &Q);
  while (Q--) {
    int type;
    scanf("%d", &type);
    int tim, x;
    scanf("%d%d", &tim, &x);
    if (!mp[x]) {
      mp[x] = ++tot;
    }
    x = mp[x];
    if (type == 1) {
      if (shi[x]) {
        jia(shi[x], tim);
      } else {
        bool flag = false;
        for (int i = 0; i < (int)v[x].size(); i++) {
          if (v[x][i].tim == tim) {
            v[x][i].ge++;
            flag = true;
            break;
          }
        }
        if (!flag) {
          node tmp;
          tmp.tim = tim;
          tmp.ge = 1;
          v[x].push_back(tmp);
        }
        if (v[x].size() > kuai) {
          build(x);
        }
      }
    } else if (type == 2) {
      if (shi[x]) {
        clear(shi[x], tim);
      } else {
        bool flag = false;
        for (int i = 0; i < (int)v[x].size(); i++) {
          if (v[x][i].tim == tim) {
            flag = true;
            v[x][i].ge--;
            break;
          }
        }
        if (!flag) {
          node tmp;
          tmp.tim = tim;
          tmp.ge = -1;
          v[x].push_back(tmp);
        }
        if (v[x].size() > kuai) {
          build(x);
        }
      }
    } else {
      if (shi[x]) {
        printf("%d\n", xunwen(shi[x], tim));
      } else {
        int res = 0;
        for (int i = 0; i < (int)v[x].size(); i++) {
          if (v[x][i].tim <= tim) {
            res += v[x][i].ge;
          }
        }
        printf("%d\n", res);
      }
    }
  }
  return 0;
}
