#include <bits/stdc++.h>
using namespace std;
int n, id;
const int N = 100001;
class query {
 public:
  int a, t, x, idx;
  query(int aa, int tt, int xx) {
    a = aa;
    t = tt;
    x = xx;
  }
  query() {}
};
query q[N];
map<int, int> mp;
vector<query> v[N];
int find(int x) {
  if (mp.find(x) == mp.end()) return mp[x] = id++;
  return mp[x];
}
int bit[N];
void add(int idx, int size, int val) {
  while (idx <= size) {
    bit[idx] += val;
    idx += idx & -idx;
  }
}
int get(int idx) {
  int ret = 0;
  while (idx) {
    ret += bit[idx];
    idx -= idx & -idx;
  }
  return ret;
}
vector<pair<int, int> > res;
int main() {
  cin >> n;
  for (int i = 0; i < n; ++i) {
    scanf("%d%d%d", &q[i].a, &q[i].t, &q[i].x);
    q[i].idx = i;
    v[find(q[i].x)].push_back(q[i]);
  }
  for (int value = 0; value < id; ++value) {
    vector<int> g;
    for (int i = 0; i < v[value].size(); ++i) g.push_back(v[value][i].t);
    sort(g.begin(), g.end());
    int size = 0;
    for (int i = 0; i < v[value].size(); ++i) {
      v[value][i].t =
          upper_bound(g.begin(), g.end(), v[value][i].t) - g.begin();
      size = max(size, v[value][i].t);
    }
    memset(bit, 0, sizeof(int) * (size + 1));
    for (int i = 0; i < v[value].size(); ++i) {
      query e = v[value][i];
      if (e.a == 1)
        add(e.t, size, 1);
      else if (e.a == 2)
        add(e.t, size, -1);
      else
        res.push_back(make_pair(e.idx, get(e.t)));
    }
  }
  sort(res.begin(), res.end());
  for (int i = 0; i < res.size(); ++i) printf("%d\n", res[i].second);
}
