from typing import List
class FenwickTree:
def __init__(self, n):
self.n = n
self.sum_seg = [0] * (self.n + 1) # 分段存储的区间和 sum_seg[x]表示的是x位置结尾,长度为x&(-x)的区间中的数值的和
# 获取区间[0, end]的数值和
def __getSumWithEnd(self, end): # 这里end是内部坐标,不是外部坐标
ans = 0
while end:
ans += self.sum_seg[end]
end &= (end - 1)
return ans
# 获取区间的数据和
def getSum(self, start, end):
start, end = start+1, end+1
if not (end >= start and start >= 1 and end <= self.n):
raise IndexError(f'bad range {(start-1, end-1)}')
if start == 1:
return self.__getSumWithEnd(end)
return self.__getSumWithEnd(end) - self.__getSumWithEnd(start-1)
# x位置增加数值delta
def addValue(self, x, delta):
x += 1
while x <= self.n:
self.sum_seg[x] += delta
x += x & (-x)
class CdqNode:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
self.cnt = 1 # 原序列中数值是(a, b, c)的节点个数
self.le_num = 0 # 原序列中所有数值等于(a, b, c)的节点X, 原序列中三维偏序小于等于(a, b, c)的节点个数(不包含X本身)
def __lt__(self, other):
if self.a != other.a:
return self.a < other.a
if self.b != other.b:
return self.b < other.b
return self.c < other.c
def __repr__(self):
return '(%d,%d,%d,%d,%d)' % (self.a, self.b, self.c, self.cnt, self.le_num)
fenwick = FenwickTree(200000 + 10)
__buf = [CdqNode(0, 0, 0) for _ in range(100005)]
merge_buf = [CdqNode(0, 0, 0) for _ in range(100005)]
def copy_node(node1, node2):
node1.a, node1.b, node1.c, node1.cnt, node1.le_num = node2.a, node2.b, node2.c, node2.cnt, node2.le_num
# 归并排序
def merge_sort(buf, ll, rr):
if ll == rr:
return
mid = (ll + rr) // 2
merge_sort(buf, ll, mid)
merge_sort(buf, mid+1, rr)
ii = ll - 1
pos = -1
for jj in range(mid+1, rr+1):
while ii+1 <= mid and buf[ii+1].b <= buf[jj].b:
ii += 1
fenwick.addValue(buf[ii].c, buf[ii].cnt)
pos += 1;
copy_node(merge_buf[pos], buf[ii])
buf[jj].le_num += fenwick.getSum(0, buf[jj].c)
pos += 1
copy_node(merge_buf[pos], buf[jj])
for i in range(ll, ii+1):
fenwick.addValue(buf[i].c, -buf[i].cnt)
while ii+1 <= mid:
ii += 1
pos += 1;
copy_node(merge_buf[pos], buf[ii])
# 归并两个子区间
for i in range(ll, rr+1):
copy_node(buf[i], merge_buf[i-ll])
# n是输入序列长度, 返回输出的序列的长度
def cdq(n) -> List:
buf = __buf[:n]
buf.sort();
# 将数值相同的节点合并为一个节点
ii = 0
for jj in range(1, n):
#if buf[ii] == buf[jj]:
if buf[ii].a == buf[jj].a and buf[ii].b == buf[jj].b and buf[ii].c == buf[jj].c:
buf[ii].cnt += 1
else:
ii += 1
copy_node(buf[ii], buf[jj])
buf[ii].cnt, buf[ii].le_num = 1, 0
merge_sort(buf, 0, ii)
for i in range(ii+1):
buf[i].le_num += buf[i].cnt - 1
return buf[:ii+1]
n, k = map(int, input().split())
pos = 0
for _ in range(n):
__buf[pos].a, __buf[pos].b, __buf[pos].c = map(int, input().split())
__buf[pos].cnt = 1
__buf[pos].le_num = 0
pos += 1
ans = [0] * n
ret = cdq(n)
for node in ret:
ans[node.le_num] += node.cnt
for i in range(n):
print(ans[i])