#include <fstream>
#include <math.h>
using namespace std;
FILE *fin=fopen("cutii.in","r");
FILE *fout=fopen("cutii.out","w");
int n,t,m[3501][3501];
struct cutie
{
int x,y,z;
} v[3501];
int maxi(int a,int b)
{
if(a>b)
return a;
return b;
}
int last(int a)
{
return (a&(~(a-1)));
}
void update2(int val,int x,int y)
{
for(int i=y; i<=n; i+=last(i))
{
m[x][i]=maxi(m[x][i],val);
}
}
void update1(int val, int x,int y)
{
for(int i=x; i<=n; i+=last(i))
{
update2(val,i,y);
}
}
void xsort()
{
int k=10,p=1;
int m[10][3501];
int c;
cutie v2[3501];
int maxim=0;
int curent;
for(int i=1; i<=n; i++)
{
curent = log10(v[i].z)+1;
if(maxim<curent)
maxim=curent;
}
while(maxim)
{
for(int i=0; i<10; i++)
m[i][0]=0;
for(int i=1; i<=n; i++)
{
c=(v[i].z%k)/p;
m[c][0]++;
m[c][m[c][0]]=i;
}
int contor=1;
for(int i=0; i<10; i++)
for(int j=1; j<=m[i][j]; j++)
v2[contor++]=v[m[i][j]];
for(int i=1; i<=n; i++)
{
v[i]=v2[i];
}
maxim--;
}
}
int querry2(int x,int y)
{
int ans=0;
for(int i=y; i>0; i-=last(i))
{
ans=maxi(m[x][i],ans);
}
return ans;
}
int querry1(int x,int y)
{
int ans=0;
for(int i=x; i>0; i-=last(i))
{
ans=maxi(querry2(i,y),ans);
}
return ans;
}
void set0_1(int val,int x,int y)
{
for(int i=y;i<=n;i+=last(i))
m[x][i]=0;
}
void set0(int val,int x,int y)
{
for(int i=x;i<=n;i+=last(i))
set0_1(val,i,y);
}
int main()
{
int k1,k2,i;
fscanf(fin,"%d%d",&n,&t);
for(k1=1; k1<=t; k1++)
{
for(k2=1; k2<=n; k2++)
fscanf(fin,"%d%d%d",&v[k2].x,&v[k2].y,&v[k2].z);
xsort();
for(i=1; i<=n; i++)
update1(querry1(v[i].x-1,v[i].y-1)+1,v[i].x,v[i].y);
fprintf(fout,"%d\n",querry1(n,n));
for(i=1; i<=n; i++)
set0(0,v[i].x,v[i].y);
}
return 0;
}