#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
struct Star {
int x, y, z; // 坐标和属性,z = 0 或 1
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<Star> stars(n);
for (int i = 0; i < n; ++i) {
cin >> stars[i].x >> stars[i].y >> stars[i].z;
}
// 排序规则:先按 x 升序,若 x 相同则按 z 降序(即 z=1 的右点排在 z=0 的左点前面)
// 这样保证了当 x 相等时,右点先被处理,不会错误地与相同 x 的左点匹配(因为要求严格小于)
sort(stars.begin(), stars.end(), [](const Star & a, const Star & b) {
if (a.x != b.x) return a.x < b.x;
return a.z > b.z; // z=1 在前,z=0 在后
});
multiset<int>
leftY; // 存储所有可用的左点(z=0)的 y 坐标,允许重复
int ans = 0;
for (const auto& s : stars) {
if (s.z == 0) {
// 左点:将其 y 加入集合,等待与后面的右点匹配
leftY.insert(s.y);
} else { // s.z == 1
// 右点:从集合中找一个 y 比当前 y 小的最大左点 y 进行匹配
// 使用 lower_bound 找到第一个 >= s.y 的位置,前一个就是 < s.y 的最大值
auto it = leftY.lower_bound(s.y);
if (it != leftY.begin()) {
--it; // 指向小于 s.y 的最大 y
leftY.erase(it); // 删除这个左点,它被匹配了
++ans;
}
// 如果找不到,则跳过该右点
}
}
cout << ans << endl;
return 0;
}