const int MAXN=1e5+5,MAXV=2e5+5;
struct Node{
int a,b,c,id;
bool lower;
bool operator < (const Node &y)const{
if(a!=y.a)return a<y.a;
if(b!=y.b)return b<y.b;
return c<y.c;
}
bool operator == (const Node &y)const{
return a==y.a&&b==y.b&&c==y.c;
}
}node[MAXN],node2[MAXN],temp[MAXN],temp2[MAXN];
int n,m,cnt[MAXN],ans[MAXN];
void cdq2(int lef,int rig){
if(lef==rig)return;
int mid=lef+rig>>1;
cdq2(lef,mid);cdq2(mid+1,rig);
int pos1=lef,pos2=mid+1,pos3=lef,s=0;
while(pos1<=mid&&pos2<=rig){
if(temp[pos1].c<=temp[pos2].c){
if(temp[pos1].lower)s+=cnt[temp[pos1].id];
temp2[pos3++]=temp[pos1++];
}
else{
if(!temp[pos2].lower)ans[temp[pos2].id]+=s;
temp2[pos3++]=temp[pos2++];
}
}
while(pos1<=mid){
if(temp[pos1].lower)s+=cnt[temp[pos1].id];
temp2[pos3++]=temp[pos1++];
}
while(pos2<=rig){
if(!temp[pos2].lower)ans[temp[pos2].id]+=s;
temp2[pos3++]=temp[pos2++];
}
_rep(i,lef,rig)temp[i]=temp2[i];
}
void cdq1(int lef,int rig){
if(lef==rig)return;
int mid=lef+rig>>1;
cdq1(lef,mid);cdq1(mid+1,rig);
int pos1=lef,pos2=mid+1,pos3=lef;
while(pos1<=mid&&pos2<=rig){
if(node2[pos1].b<=node2[pos2].b)
node2[pos1].lower=true,temp[pos3++]=node2[pos1++];
else
node2[pos2].lower=false,temp[pos3++]=node2[pos2++];
}
while(pos1<=mid)node2[pos1].lower=true,temp[pos3++]=node2[pos1++];
while(pos2<=rig)node2[pos2].lower=false,temp[pos3++]=node2[pos2++];
_rep(i,lef,rig)node2[i]=temp[i];
cdq2(lef,rig);
}
int f[MAXN];
int main()
{
n=read_int(),m=read_int();
_for(i,0,n)
node[i].a=read_int(),node[i].b=read_int(),node[i].c=read_int();
sort(node,node+n);
memcpy(node2,node,sizeof(node2));
int t=unique(node2,node2+n)-node2;
for(int i=0,j=0;i<n;j++){
while(node[i]==node2[j]&&i<n)
cnt[j]++,i++;
node2[j].id=j;
}
cdq1(0,t-1);
_for(i,0,t)
f[ans[i]+cnt[i]-1]+=cnt[i];
_for(i,0,n)
enter(f[i]);
return 0;
}