#include <bits/stdc++.h>
using namespace std;
int GetSum(vector<int> &tree, int x) {
  int result = 0;
  for (int i = x; i >= 0; i = (i & (i + 1)) - 1) {
    result += tree[i];
  }
  return result;
}
void Update(vector<int> &tree, int x, int delta) {
  int size = (int)tree.size();
  for (int i = x; i < size; i = (i | (i + 1))) {
    tree[i] += delta;
  }
}
struct Vertex {
  int type;
  int time;
  int value;
};
const int MAX_N = 100100;
Vertex events[MAX_N];
vector<vector<int> > nums;
vector<vector<int> > trees;
int main() {
  int n;
  scanf("%d", &n);
  map<int, pair<int, int> > num;
  for (int i = 0; i < n; ++i) {
    scanf("%d %d %d", &events[i].type, &events[i].time, &events[i].value);
    if (!num.count(events[i].value)) {
      int value = num.size();
      num[events[i].value] = {value, 0};
      nums.push_back(vector<int>());
      trees.push_back(vector<int>());
    }
    num[events[i].value].second++;
    nums[num[events[i].value].first].push_back(events[i].time);
  }
  map<int, int> times;
  for (auto pos = num.begin(); pos != num.end(); ++pos) {
    trees[pos->second.first].resize(pos->second.second);
    sort(nums[pos->second.first].begin(), nums[pos->second.first].end());
    for (int i = 0; i < pos->second.second; ++i) {
      int value = i;
      times[nums[pos->second.first][i]] = value;
    }
  }
  for (int i = 0; i < n; ++i) {
    int num_tree = num[events[i].value].first;
    int num_elem = times[events[i].time];
    if (events[i].type == 1) {
      Update(trees[num_tree], num_elem, 1);
    } else if (events[i].type == 2) {
      Update(trees[num_tree], num_elem, -1);
    } else {
      printf("%d\n", GetSum(trees[num_tree], num_elem));
    }
  }
  return 0;
}
