rt
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
namespace Quick_Function {
template <typename Temp> void Read(Temp &x) {
x = 0; char ch = getchar(); bool op = 0;
while(ch < '0' || ch > '9') { if(ch == '-') op = 1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); }
if(op) x = -x;
}
template <typename T, typename... Args> void Read(T &t, Args &... args) { Read(t); Read(args...); }
template <typename Temp> Temp Max(Temp x, Temp y) { return x > y ? x : y; }
template <typename Temp> Temp Min(Temp x, Temp y) { return x < y ? x : y; }
template <typename Temp> Temp Abs(Temp x) { return x < 0 ? (-x) : x; }
template <typename Temp> void Swap(Temp &x, Temp &y) { x ^= y ^= x ^= y; }
}
using namespace Quick_Function;
const int MAXN = 2e6 + 5;
int ans[MAXN], cnt[MAXN];
int Anstot;
struct Bit {
int bit[MAXN], Size;
void Build(int x) { Size = x; }
int Lowbit(int i) { return i & -i; }
void Update(int x, int k) {
if(x == 0) return;
for(int i = x; i <= Size; i += Lowbit(i)) bit[i] += k;
}
int Query_Sum(int x) {
int res = 0;
for(int i = x; i; i -= Lowbit(i)) res += bit[i];
return res;
}
};
Bit tree;
struct CDQ_Node {
int A_val, B_Val, C_Val, IdxAns, flag;
friend bool operator < (CDQ_Node x, CDQ_Node y) { return x.A_val != y.A_val ? x.A_val < y.A_val : (x.B_Val != y.B_Val ? x.B_Val < y.B_Val : (x.C_Val != y.C_Val ? x.C_Val < y.C_Val : x.flag > y.flag)); }
};
struct CDQ {
CDQ_Node qst[MAXN], tmp[MAXN];
int cnt;
void Solve(int l, int r) {
if(l == r) return;
int mid = (l + r) >> 1;
Solve(l, mid); Solve(mid + 1, r);
int i = l, j = mid + 1, tot = 1;
while(i <= mid && j <= r) {
if(qst[i].B_Val < qst[j].B_Val) {
if(qst[i].flag) tree.Update(qst[i].C_Val, 1);
tmp[tot++] = qst[i++];
}
else {
if(!qst[j].flag) ans[qst[j].IdxAns] += tree.Query_Sum(qst[j].C_Val);
tmp[tot++] = qst[j++];
}
}
while(i <= mid) {
if(qst[i].flag) tree.Update(qst[i].C_Val, 1);
tmp[tot++] = qst[i++];
}
while(j <= r) {
if(!qst[j].flag) ans[qst[j].IdxAns] += tree.Query_Sum(qst[j].C_Val);
tmp[tot++] = qst[j++];
}
for(int k = l; k <= mid; k++) if(qst[k].flag) tree.Update(qst[k].C_Val, -1);
for(int k = 1; k < tot; k++) qst[k + l - 1] = tmp[k];
}
};
CDQ cdq;
int n, k;
int main() {
Read(n, k); tree.Build(MAXN - 5);
for(int i = 1; i <= n; i++) {
Read(cdq.qst[i].A_val, cdq.qst[i].B_Val, cdq.qst[i].C_Val);
cdq.qst[i + n] = cdq.qst[i];
cdq.qst[i].flag = 0, cdq.qst[i].IdxAns = i;
cdq.qst[i + n].flag = 1;
}
sort(cdq.qst + 1, cdq.qst + 1 + 2 * n);
// for(int i = 1; i <= 2 * n; i++) printf("%d %d %d %d\n", cdq.qst[i].A_val, cdq.qst[i].B_Val, cdq.qst[i].C_Val, cdq.qst[i].IdxAns);
cdq.Solve(1, 2 * n);
for(int i = 1; i <= n; i++) cnt[ans[i] - 1]++;
for(int i = 0; i < n; i++) printf("%d\n", cnt[i]);
return 0;
}