#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 3500
struct aa{
int x, y;
}val[MAXN+1];
int r, lista[MAXN+1], nxt[MAXN+1], n, m, aib[MAXN+1][MAXN+1];
inline int maxim(int a, int b){
return (a>b ? a : b);
}
inline void adauga(int x, int y, int z)
{
val[++r].x = y;
val[r].y = z;
nxt[r] = lista[x];
lista[x] = r;
}
inline int query(int x, int y)
{
int mx = 0, cy = y;
for(; x>=1; x-=(x&-x))
for(y = cy; y>=1; y-=(y&-y))
mx = maxim(mx, aib[x][y]);
return mx;
}
inline void update(int x, int y, int val)
{
int cy = y;
for(; x<=n; x+=(x&-x))
for(y = cy; y<=n; y+=(y&-y))
aib[x][y] = maxim(aib[x][y], val);
}
int main()
{
freopen("cutii.in", "r", stdin);
freopen("cutii.out", "w", stdout);
int a, i, t, ans, x, y, z, p, c;
scanf("%d%d", &n, &t);
for(a=1; a<=t; ++a)
{
ans = 0;
for(i=1; i<=n; ++i){
scanf("%d%d%d", &x, &y, &z);
adauga(x, y, z);
}
for(i=1; i<=n; ++i)
{
p = lista[i];
while(p)
{
c = query(val[p].x-1, val[p].y-1) + 1;
ans = maxim(ans, c);
update(val[p].x, val[p].y, c);
p = nxt[p];
}
}
printf("%d\n", ans);
memset(lista, 0, sizeof(lista));
r = 0;
for(i=1; i<=n; ++i)
memset(aib[i], 0, sizeof(aib[i]));
}
return 0;
}