#include <bits/stdc++.h>
using namespace std;
struct query {
  int type, tim, val, newtim, id;
};
query foo[100005];
bool cmp(query a, query b) {
  if (a.val != b.val) return a.val < b.val;
  if (a.tim != b.tim) return a.tim < b.tim;
  return a.id < b.id;
}
bool newcmp(query a, query b) { return a.id < b.id; }
vector<int> yale[100005];
unordered_map<int, int> valmap;
vector<int> temp;
void update(int id, int pos, int dx) {
  for (int i = pos; i < (int)yale[id].size(); i += i & (-i)) {
    yale[id][i] += dx;
  }
}
int ask(int id, int pos) {
  int sum = 0;
  for (int i = pos; i; i -= i & (-i)) {
    sum += yale[id][i];
  }
  return sum;
}
int main() {
  int q;
  scanf("%d", &q);
  for (int i = 0; i < q; i++) {
    scanf("%d %d %d", &foo[i].type, &foo[i].tim, &foo[i].val);
    foo[i].id = i;
    temp.push_back(foo[i].val);
  }
  sort(temp.begin(), temp.end());
  temp.resize(unique(temp.begin(), temp.end()) - temp.begin());
  for (int i = 0; i < (int)temp.size(); i++) {
    valmap[temp[i]] = i + 1;
  }
  sort(foo, foo + q, cmp);
  for (int i = 0; i < q; i++) {
    if (!i || foo[i].val != foo[i - 1].val) {
      yale[valmap[foo[i].val]].assign(2, 0);
      foo[i].newtim = 1;
    } else {
      yale[valmap[foo[i].val]].push_back(0);
      foo[i].newtim = foo[i - 1].newtim + 1;
    }
  }
  sort(foo, foo + q, newcmp);
  for (int i = 0; i < q; i++) {
    if (foo[i].type == 1) {
      update(valmap[foo[i].val], foo[i].newtim, 1);
    } else if (foo[i].type == 2) {
      update(valmap[foo[i].val], foo[i].newtim, -1);
    } else {
      printf("%d\n", ask(valmap[foo[i].val], foo[i].newtim));
    }
  }
}
