class UnionFind: def __init__(self, n): self.n = n self.parents = [-1] * n self._left = [i for i in range(n)] self._right = [i for i in range(n)] def find(self, x): """ 根を見つける関数を定義(同時にxを直接根にくっつける操作も行う)""" tmp = [] parents = self.parents while parents[x] >= 0: tmp.append(x) x = parents[x] for y in tmp: parents[y] = x return x def union(self, x, y): """ 二つの木をくっつける(子を多く持つ方を根とした親子関係)。これは破壊的操作を行う。""" x = self.find(x) y = self.find(y) if x == y: return if self.parents[x] > self.parents[y]: x, y = y, x self.parents[x] += self.parents[y] self.parents[y] = x self._left[x] = min(self._left[x],self._left[y]) self._right[x] = max(self._right[x],self._right[y]) def union_range(self, l, r): """ 閉区間[l,r]の要素をくっつける """ if l>r: return while self._right[l]=N: continue U.union_range(l,r-1) if r-l>0: U.union(i,l) for i in range(N): print(U.size(i))