#include <cstdio>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
int N, T;
template<int D, int Sz, int... SzArgs>
struct FenwickTree {
FenwickTree<D - 1, SzArgs...> tree[Sz];
template<typename T = int, typename... Args>
void update(int val, int x, Args... args) {
for(int i = x; i < Sz; i += (i & -i)) {
tree[i].update(val, args...);
}
}
template<typename T = int, typename... Args>
int query(int x, Args... args) {
int ret = 0;
for(int i = x; i > 0; i -= (i & -i))
ret = max(ret, tree[i].query(args...));
return ret;
}
};
template<int Sz>
struct FenwickTree<1, Sz> {
int tree[Sz] = {0};
template<typename T = int>
void update(int val, int x) {
for(int i = x; i < Sz; i += (i & -i)) {
tree[i] = max(tree[i], val);
}
}
template<typename T = int>
int query(int x) {
int ret = 0;
for (int i = x; i > 0; i -= (i & -i))
ret = max(ret, tree[i]);
return ret;
}
};
struct cutie {
int x, y, z;
cutie(int x, int y, int z) : x(x), y(y), z(z) { }
};
#define cmp(c) \
[] (const cutie& a, const cutie& b) -> bool { \
return a.c < b.c; \
}
FenwickTree<2, 3501, 3501> *fen = NULL;
void solve_test() {
vector<cutie> cutii;
// read
for(int i = 0; i < N; ++i) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
cutii.push_back(cutie(x, y, z));
}
// sort
sort(cutii.begin(), cutii.end(), cmp(x));
int best = 0;
fen = new FenwickTree<2, 3501, 3501>();
for(const auto& c : cutii) {
int q = 1 + fen->query(c.y - 1, c.z - 1);
best = max(best, q);
fen->update(q, c.y, c.z);
}
delete fen;
fen = NULL;
printf("%d\n", best);
}
int main(int argc, char *argv[]) {
freopen("cutii.in", "r", stdin);
freopen("cutii.out", "w", stdout);
scanf("%d%d", &N, &T);
while(T--) solve_test();
return 0;
}