#include <bits/stdc++.h>
using namespace std;
const int MOD = (int)7 + (int)1e9;
const int N = 1000005;
const double PI = 4 * atan(1);
const double eps = 1e-10;
const long long oo = 1e10;
const int K = 26;
struct query {
  int a, t, x;
  query() { a = -1, t = -1, x = -1; }
  query(int _a, int _t, int _x) {
    a = (_a);
    t = (_t);
    x = (_x);
  }
};
int n;
unordered_map<int, int> ma;
vector<query> qu;
set<int> ss;
set<int> t[N];
unordered_map<int, int> maa[N];
int mx = 1;
int mt = 0;
int sz[N];
vector<int> tree[N];
void update(int val, int pos, int upd) {
  for (; pos <= sz[val]; pos += (pos) & (-pos)) {
    tree[val][pos] += upd;
  }
}
int get(int val, int pos) {
  int to = 0;
  for (; pos; pos -= (pos) & (-pos)) {
    to += tree[val][pos];
  }
  return to;
}
void ins(int x, int t) { update(x, t, 1); }
void rem(int x, int t) { update(x, t, -1); }
int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  cin >> n;
  for (int i = 0; i < n; i++) {
    int x, y, w;
    cin >> x >> y >> w;
    qu.push_back(query(x, y, w));
    ss.insert(w);
  }
  for (int u : ss) {
    ma[u] = mx++;
  }
  for (query& q : qu) {
    q.x = ma[q.x];
    t[q.x].insert(q.t);
  }
  for (int i = 1; i <= mx; i++) {
    if (t[i].size() == 0) continue;
    mt = 1;
    for (int u : t[i]) {
      maa[i][u] = mt++;
    }
    sz[i] = mt;
    tree[i].resize(sz[i] + 1);
  }
  for (query& q : qu) {
    q.t = maa[q.x][q.t];
  }
  for (query q : qu) {
    if (q.a == 1) {
      ins(q.x, q.t);
    } else if (q.a == 2) {
      rem(q.x, q.t);
    } else {
      cout << get(q.x, q.t) << endl;
    }
  }
  return 0;
}
