Buggy python submission (verdict: Time Limit Exceeded):
from bisect import bisect_left
from collections import Counter
import sys

def main():
    input = sys.stdin.readline
    N = int(input().rstrip())
    # Union-Find
    parent = list(range(N))
    rank = [1] * N
    def get_root(node):
      if parent[node] == node:
        return node
      root = get_root(parent[node])
      parent[node] = root
      return root
    
    def union(a, b):
      root_a = get_root(a)
      root_b = get_root(b)
      if root_a == root_b:
        return
      rank_a = rank[root_a]
      rank_b = rank[root_b]
      if rank_a < rank_b:
        parent[root_a] = root_b
      else:
        parent[root_b] = root_a
        if rank_a == rank_b:
          rank[root_a] += 1
    XYs = []
    XYs1 = []
    XYs2 = []
    for i in range(N):
        x, y = map(int, input().rstrip().split())
        XYs.append([x, y, i])
        XYs2.append([N-x, N-y, i])
    XYs1 = sorted(XYs)
    XYs2.sort()
    
    BL = (N+1).bit_length()
    WIDTH = pow(2, BL)
    BUFSIZE = pow(2, BL+1) - 1
    BASE = BUFSIZE - WIDTH
     
    def update(buf, i, x):
        buf[BASE + i] = x
        i += BASE
        i = (i-1) // 2
        while i >= 0:
            buf[i] = compare(buf[2*i+1], buf[2*i+2], False)
            i = (i-1) // 2
     
    # [q_left, q_right]
    def search(buf, l, width, i, q_left, q_right):
        if q_right < l or l + width - 1 < q_left:
            return None
        if q_left <= l and l + width - 1 <= q_right:
            return buf[i]
        nwidth = width // 2
        c1 = search(buf, l, nwidth, 2*i+1, q_left, q_right)
        c2 = search(buf, l+nwidth, nwidth, 2*i+2, q_left, q_right)
        return compare(c1, c2, True)
     
    def compare(c1, c2, flag=False):
        if c1 is None:
            return c2
        if c2 is None:
            return c1
        if flag:
            union(c1, c2)
        return get_root(c1)
     
    buf1 = [None for _ in range(BUFSIZE)]
    for x, y, k in XYs1:
        node = search(buf1, 0, WIDTH, 0, 0, y-1)
        if node is not None:
            union(k, node)
        else:
            update(buf1, y, k)
    
    buf1 = [None for _ in range(BUFSIZE)]
    for x, y, k in XYs2:
        node = search(buf1, 0, WIDTH, 0, 0, y-1)
        if node is not None:
            union(k, node)
        else:
            update(buf1, y, k)

    ct = Counter()
    for i in range(N):
        ct[get_root(i)] += 1
    
    for p in parent:
        print(ct[p])

main()


Fixed submission:
from bisect import bisect_left
from collections import Counter
import sys

def main():
    input = sys.stdin.readline
    N = int(input().rstrip())
    # Union-Find
    parent = list(range(N))
    rank = [1] * N
    def get_root(node):
      if parent[node] == node:
        return node
      root = get_root(parent[node])
      parent[node] = root
      return root
    
    def union(a, b):
      root_a = get_root(a)
      root_b = get_root(b)
      if root_a == root_b:
        return
      rank_a = rank[root_a]
      rank_b = rank[root_b]
      if rank_a < rank_b:
        parent[root_a] = root_b
      else:
        parent[root_b] = root_a
        if rank_a == rank_b:
          rank[root_a] += 1

    XYs = []
    XYs1 = []
    XYs2 = []
    for i in range(N):
        x, y = map(int, input().rstrip().split())
        XYs.append([x, y, i])
        XYs2.append([N-x, N-y, i])
    XYs1 = sorted(XYs)
    XYs2.sort()
    
    buf = []
    L = 0
    for x, y, k in XYs1:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1
    
    buf = []
    L = 0
    for x, y, k in XYs2:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1

    ct = Counter()
    for i in range(N):
        ct[get_root(i)] += 1
    
    for p in parent:
        print(ct[p])

main()

Buggy python submission (verdict: Time Limit Exceeded):
from bisect import bisect_left
from collections import Counter
import sys

def main():
    input = sys.stdin.readline
    N = int(input().rstrip())
    # Union-Find
    parent = [i for i in range(N)]
    rank = [1] * N
    def get_root(node):
      if parent[node] == node:
        return node
      root = get_root(parent[node])
      parent[node] = root
      return root
    
    def union(a, b):
      root_a = get_root(a)
      rank_a = rank[root_a]
      root_b = get_root(b)
      rank_b = rank[root_b]
      if root_a == root_b:
        return
      if rank_a < rank_b:
        parent[root_a] = root_b
      else:
        parent[root_b] = root_a
        if rank_a == rank_b:
          rank[root_a] += 1
    XYs = []
    XYs1 = []
    XYs2 = []
    for i in range(N):
        x, y = map(int, input().rstrip().split())
        XYs.append([x, y, i])
        XYs2.append([N-x, N-y, i])
    XYs1 = sorted(XYs)
    XYs2.sort()
    
    BL = (N+1).bit_length()
    WIDTH = pow(2, BL)
    BUFSIZE = pow(2, BL+1) - 1
    BASE = BUFSIZE - WIDTH
     
    def update(buf, i, x):
        buf[BASE + i] = x
        i += BASE
        i = (i-1) // 2
        while i >= 0:
            buf[i] = compare(buf[2*i+1], buf[2*i+2], False)
            i = (i-1) // 2
     
    # [q_left, q_right]
    def search(buf, l, width, i, q_left, q_right):
        if q_right < l or l + width - 1 < q_left:
            return None
        if q_left <= l and l + width - 1 <= q_right:
            return buf[i]
        nwidth = width // 2
        c1 = search(buf, l, nwidth, 2*i+1, q_left, q_right)
        c2 = search(buf, l+nwidth, nwidth, 2*i+2, q_left, q_right)
        return compare(c1, c2, True)
     
    def compare(c1, c2, flag=False):
        if c1 is None:
            return c2
        if c2 is None:
            return c1
        if flag:
            union(c1, c2)
        return get_root(c1)
     
    buf1 = [None for _ in range(BUFSIZE)]
    for x, y, k in XYs1:
        node = search(buf1, 0, WIDTH, 0, 0, y-1)
        if node is not None:
            union(k, node)
        else:
            update(buf1, y, k)
    
    buf1 = [None for _ in range(BUFSIZE)]
    for x, y, k in XYs2:
        node = search(buf1, 0, WIDTH, 0, 0, y-1)
        if node is not None:
            union(k, node)
        else:
            update(buf1, y, k)
     
    for i in range(N):
        get_root(i)
    
    ct = Counter(parent)
    for i in range(N):
        print(ct[parent[i]])

main()


Fixed submission:
from bisect import bisect_left
from collections import Counter
import sys

def main():
    input = sys.stdin.readline
    N = int(input().rstrip())
    # Union-Find
    parent = list(range(N))
    rank = [1] * N
    def get_root(node):
      if parent[node] == node:
        return node
      root = get_root(parent[node])
      parent[node] = root
      return root
    
    def union(a, b):
      root_a = get_root(a)
      root_b = get_root(b)
      if root_a == root_b:
        return
      rank_a = rank[root_a]
      rank_b = rank[root_b]
      if rank_a < rank_b:
        parent[root_a] = root_b
      else:
        parent[root_b] = root_a
        if rank_a == rank_b:
          rank[root_a] += 1

    XYs = []
    XYs1 = []
    XYs2 = []
    for i in range(N):
        x, y = map(int, input().rstrip().split())
        XYs.append([x, y, i])
        XYs2.append([N-x, N-y, i])
    XYs1 = sorted(XYs)
    XYs2.sort()
    
    buf = []
    L = 0
    for x, y, k in XYs1:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1
    
    buf = []
    L = 0
    for x, y, k in XYs2:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1

    ct = Counter()
    for i in range(N):
        ct[get_root(i)] += 1
    
    for p in parent:
        print(ct[p])

main()

Buggy python submission (verdict: Time Limit Exceeded):
from bisect import bisect_left
from collections import Counter
import sys

input = sys.stdin.readline

N = int(input().rstrip())
# Union-Find
parent = [i for i in range(N)]
rank = [1] * N
def get_root(node):
  global parent
  if parent[node] == node:
    return node
  root = get_root(parent[node])
  parent[node] = root
  return root

def union(a, b):
  global parent
  global rank
  root_a = get_root(a)
  rank_a = rank[root_a]
  root_b = get_root(b)
  rank_b = rank[root_b]
  if root_a == root_b:
    return
  if rank_a < rank_b:
    parent[root_a] = root_b
  else:
    parent[root_b] = root_a
    if rank_a == rank_b:
      rank[root_a] += 1

def main():
    XYs = []
    XYs1 = []
    XYs2 = []
    for i in range(N):
        x, y = map(int, input().rstrip().split())
        XYs.append([x, y, i])
        XYs2.append([N-x, N-y, i])
    XYs1 = sorted(XYs)
    XYs2.sort()
    
    BL = (N+1).bit_length()
    WIDTH = pow(2, BL)
    BUFSIZE = pow(2, BL+1) - 1
    BASE = BUFSIZE - WIDTH
     
    def update(buf, i, x):
        buf[BASE + i] = x
        i += BASE
        i = (i-1) // 2
        while i >= 0:
            buf[i] = compare(buf[2*i+1], buf[2*i+2], False)
            i = (i-1) // 2
     
    # [q_left, q_right]
    def search(buf, l, width, i, q_left, q_right):
        if q_right < l or l + width - 1 < q_left:
            return None
        if q_left <= l and l + width - 1 <= q_right:
            return buf[i]
        nwidth = width // 2
        c1 = search(buf, l, nwidth, 2*i+1, q_left, q_right)
        c2 = search(buf, l+nwidth, nwidth, 2*i+2, q_left, q_right)
        return compare(c1, c2, True)
     
    def compare(c1, c2, flag=False):
        if c1 is None:
            return c2
        if c2 is None:
            return c1
        if flag:
            union(c1, c2)
        return get_root(c1)
     
    buf1 = [None for _ in range(BUFSIZE)]
    for x, y, k in XYs1:
        node = search(buf1, 0, WIDTH, 0, 0, y-1)
        if node is not None:
            union(k, node)
        else:
            update(buf1, y, k)
    
    buf1 = [None for _ in range(BUFSIZE)]
    for x, y, k in XYs2:
        node = search(buf1, 0, WIDTH, 0, 0, y-1)
        if node is not None:
            union(k, node)
        else:
            update(buf1, y, k)
     
    for i in range(N):
        get_root(i)
    
    ct = Counter(parent)
    for i in range(N):
        print(ct[parent[i]])

main()


Fixed submission:
from bisect import bisect_left
from collections import Counter
import sys

def main():
    input = sys.stdin.readline
    N = int(input().rstrip())
    # Union-Find
    parent = list(range(N))
    rank = [1] * N
    def get_root(node):
      if parent[node] == node:
        return node
      root = get_root(parent[node])
      parent[node] = root
      return root
    
    def union(a, b):
      root_a = get_root(a)
      root_b = get_root(b)
      if root_a == root_b:
        return
      rank_a = rank[root_a]
      rank_b = rank[root_b]
      if rank_a < rank_b:
        parent[root_a] = root_b
      else:
        parent[root_b] = root_a
        if rank_a == rank_b:
          rank[root_a] += 1

    XYs = []
    XYs1 = []
    XYs2 = []
    for i in range(N):
        x, y = map(int, input().rstrip().split())
        XYs.append([x, y, i])
        XYs2.append([N-x, N-y, i])
    XYs1 = sorted(XYs)
    XYs2.sort()
    
    buf = []
    L = 0
    for x, y, k in XYs1:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1
    
    buf = []
    L = 0
    for x, y, k in XYs2:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1

    ct = Counter()
    for i in range(N):
        ct[get_root(i)] += 1
    
    for p in parent:
        print(ct[p])

main()

Buggy python submission (verdict: Time Limit Exceeded):
from bisect import bisect_left
from collections import Counter
import sys

input = sys.stdin.readline

N = int(input().rstrip())
# Union-Find
parent = [i for i in range(N)]
rank = [1] * N
def get_root(node):
  global parent
  if parent[node] == node:
    return node
  root = get_root(parent[node])
  parent[node] = root
  return root

def union(a, b):
  global parent
  global rank
  root_a = get_root(a)
  rank_a = rank[root_a]
  root_b = get_root(b)
  rank_b = rank[root_b]
  if root_a == root_b:
    return
  if rank_a < rank_b:
    parent[root_a] = root_b
  else:
    parent[root_b] = root_a
    if rank_a == rank_b:
      rank[root_a] += 1

def main():
    XYs = []
    XYs1 = []
    XYs2 = []
    for i in range(N):
        x, y = map(int, input().rstrip().split())
        XYs.append([x, y, i])
        XYs2.append([N-x, N-y, i])
    XYs1 = sorted(XYs)
    XYs2.sort()
    
    BL = (N+1).bit_length()
    WIDTH = pow(2, BL)
    BUFSIZE = pow(2, BL+1) - 1
    BASE = BUFSIZE - WIDTH
     
    def update(buf, i, x):
        buf[BASE + i] = x
        i += BASE
        i = (i-1) // 2
        while i >= 0:
            buf[i] = compare(buf[2*i+1], buf[2*i+2])
            i = (i-1) // 2
     
    # [q_left, q_right]
    def search(buf, l, width, i, q_left, q_right):
        if q_right < l or l + width - 1 < q_left:
            return set()
        if q_left <= l and l + width - 1 <= q_right:
            return buf[i]
        nwidth = width // 2
        c1 = search(buf, l, nwidth, 2*i+1, q_left, q_right)
        c2 = search(buf, l+nwidth, nwidth, 2*i+2, q_left, q_right)
        return compare(c1, c2)
     
    def compare(c1, c2):
        if not c1:
            return c2
        if not c2:
            return c1
        return c1 | c2
     
    buf1 = [set() for _ in range(BUFSIZE)]
    prevX = None
    for x, y, k in XYs1:
        nodes = search(buf1, 0, WIDTH, 0, 0, y-1)
        if nodes:
            for k2 in nodes:
                union(k, k2)
            p = get_root(k2)
            for k2 in nodes:
                update(buf1, XYs[k][1], set([p]))
        else:
            update(buf1, y, set([k]))
        prevX = x
    
    buf1 = [set() for _ in range(BUFSIZE)]
    for x, y, k in XYs2:
        nodes = search(buf1, 0, WIDTH, 0, 0, y-1)
        if nodes:
            for k2 in nodes:
                union(k, k2)
            p = get_root(k2)
            for k2 in nodes:
                update(buf1, XYs[k][1], set([p]))
        else:
            update(buf1, y, set([k]))
        prevX = x
     
    for i in range(N):
        get_root(i)
    
    ct = Counter(parent)
    for i in range(N):
        print(ct[parent[i]])

main()


Fixed submission:
from bisect import bisect_left
from collections import Counter
import sys

def main():
    input = sys.stdin.readline
    N = int(input().rstrip())
    # Union-Find
    parent = list(range(N))
    rank = [1] * N
    def get_root(node):
      if parent[node] == node:
        return node
      root = get_root(parent[node])
      parent[node] = root
      return root
    
    def union(a, b):
      root_a = get_root(a)
      root_b = get_root(b)
      if root_a == root_b:
        return
      rank_a = rank[root_a]
      rank_b = rank[root_b]
      if rank_a < rank_b:
        parent[root_a] = root_b
      else:
        parent[root_b] = root_a
        if rank_a == rank_b:
          rank[root_a] += 1

    XYs = []
    XYs1 = []
    XYs2 = []
    for i in range(N):
        x, y = map(int, input().rstrip().split())
        XYs.append([x, y, i])
        XYs2.append([N-x, N-y, i])
    XYs1 = sorted(XYs)
    XYs2.sort()
    
    buf = []
    L = 0
    for x, y, k in XYs1:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1
    
    buf = []
    L = 0
    for x, y, k in XYs2:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1

    ct = Counter()
    for i in range(N):
        ct[get_root(i)] += 1
    
    for p in parent:
        print(ct[p])

main()

Buggy python submission (verdict: Time Limit Exceeded):
from bisect import bisect_left
from collections import Counter
import sys

input = sys.stdin.readline

N = int(input().rstrip())
# Union-Find
parent = [i for i in range(N)]
rank = [1] * N
def get_root(node):
  global parent
  if parent[node] == node:
    return node
  root = get_root(parent[node])
  parent[node] = root
  return root

def union(a, b):
  global parent
  global rank
  root_a = get_root(a)
  rank_a = rank[root_a]
  root_b = get_root(b)
  rank_b = rank[root_b]
  if root_a == root_b:
    return
  if rank_a < rank_b:
    parent[root_a] = root_b
  else:
    parent[root_b] = root_a
    if rank_a == rank_b:
      rank[root_a] += 1

def main():
    XYs = []
    XYs1 = []
    XYs2 = []
    for i in range(N):
        x, y = map(int, input().rstrip().split())
        XYs.append([x, y, i])
        XYs2.append([N-x, N-y, i])
    XYs1 = sorted(XYs)
    XYs2.sort()
    
    BL = (N+1).bit_length()
    WIDTH = pow(2, BL)
    BUFSIZE = pow(2, BL+1) - 1
    BASE = BUFSIZE - WIDTH
     
    def update(buf, i, x):
        buf[BASE + i] = x
        i += BASE
        i = (i-1) // 2
        while i >= 0:
            buf[i] = compare(buf[2*i+1], buf[2*i+2])
            i = (i-1) // 2
     
    # [q_left, q_right]
    def search(buf, l, width, i, q_left, q_right):
        if q_right < l or l + width - 1 < q_left:
            return set()
        if q_left <= l and l + width - 1 <= q_right:
            return buf[i]
        nwidth = width // 2
        c1 = search(buf, l, nwidth, 2*i+1, q_left, q_right)
        c2 = search(buf, l+nwidth, nwidth, 2*i+2, q_left, q_right)
        return compare(c1, c2)
     
    def compare(c1, c2):
        if not c1:
            return c2
        if not c2:
            return c1
        return c1 | c2
     
    buf1 = [set() for _ in range(BUFSIZE)]
    prevX = None
    for x, y, k in XYs1:
        nodes = search(buf1, 0, WIDTH, 0, 0, y-1)
        if nodes:
            for k2 in nodes:
                union(k, k2)
            p = get_root(k2)
            for k2 in nodes:
                update(buf1, XYs[k][1], set([p]))
        else:
            update(buf1, y, set([k]))
        prevX = x
    
    buf1 = [set() for _ in range(BUFSIZE)]
    for x, y, k in XYs2:
        nodes = search(buf1, 0, WIDTH, 0, 0, y-1)
        if nodes:
            for k2 in nodes:
                union(k, k2)
            p = get_root(k2)
            for k2 in nodes:
                update(buf1, XYs[k][1], set([p]))
        else:
            update(buf1, y, set([k]))
        prevX = x
     
    for i in range(N):
        get_root(i)
    
    ct = Counter(parent)
    for i in range(N):
        print(ct[parent[i]])

main()


Fixed submission:
from bisect import bisect_left
from collections import Counter
import sys

def main():
    input = sys.stdin.readline
    N = int(input().rstrip())
    # Union-Find
    parent = list(range(N))
    rank = [1] * N
    def get_root(node):
      if parent[node] == node:
        return node
      root = get_root(parent[node])
      parent[node] = root
      return root
    
    def union(a, b):
      root_a = get_root(a)
      root_b = get_root(b)
      if root_a == root_b:
        return
      rank_a = rank[root_a]
      rank_b = rank[root_b]
      if rank_a < rank_b:
        parent[root_a] = root_b
      else:
        parent[root_b] = root_a
        if rank_a == rank_b:
          rank[root_a] += 1

    XYs = []
    XYs1 = []
    XYs2 = []
    for i in range(N):
        x, y = map(int, input().rstrip().split())
        XYs.append([x, y, i])
        XYs2.append([N-x, N-y, i])
    XYs1 = sorted(XYs)
    XYs2.sort()
    
    buf = []
    L = 0
    for x, y, k in XYs1:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1
    
    buf = []
    L = 0
    for x, y, k in XYs2:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1

    ct = Counter()
    for i in range(N):
        ct[get_root(i)] += 1
    
    for p in parent:
        print(ct[p])

main()

Buggy python submission (verdict: Time Limit Exceeded):
from bisect import bisect_left
from collections import Counter
import sys

input = sys.stdin.readline

N = int(input().rstrip())
# Union-Find
parent = [i for i in range(N)]
rank = [1] * N
def get_root(node):
  global parent
  if parent[node] == node:
    return node
  root = get_root(parent[node])
  parent[node] = root
  return root

def union(a, b):
  global parent
  global rank
  root_a = get_root(a)
  rank_a = rank[root_a]
  root_b = get_root(b)
  rank_b = rank[root_b]
  if root_a == root_b:
    return
  if rank_a < rank_b:
    parent[root_a] = root_b
  else:
    parent[root_b] = root_a
    if rank_a == rank_b:
      rank[root_a] += 1

def main():
    XYs = []
    XYs2 = []
    for i in range(N):
        x, y = map(int, input().rstrip().split())
        XYs.append([x, y, i])
        XYs2.append([N-x, N-y, i])
    XYs.sort()
    XYs2.sort()
    
    BL = (200001).bit_length()
    WIDTH = pow(2, BL)
    BUFSIZE = pow(2, BL+1) - 1
    BASE = BUFSIZE - WIDTH
     
    def update(buf, i, x):
        buf[BASE + i] = x
        i += BASE
        i = (i-1) // 2
        while i >= 0:
            buf[i] = compare(buf[2*i+1], buf[2*i+2])
            i = (i-1) // 2
     
    # [q_left, q_right]
    def search(buf, l, width, i, q_left, q_right):
        if q_right < l or l + width - 1 < q_left:
            return set()
        if q_left <= l and l + width - 1 <= q_right:
            return buf[i]
        nwidth = width // 2
        c1 = search(buf, l, nwidth, 2*i+1, q_left, q_right)
        c2 = search(buf, l+nwidth, nwidth, 2*i+2, q_left, q_right)
        return compare(c1, c2)
     
    def compare(c1, c2):
        if not c1:
            return c2
        if not c2:
            return c1
        return c1 | c2
     
    buf1 = [set() for _ in range(BUFSIZE)]
    prevX = None
    for x, y, k in XYs:
        nodes = search(buf1, 0, WIDTH, 0, 0, y-1)
        if nodes:
            for k2 in nodes:
                union(k, k2)
        else:
            update(buf1, y, set([k]))
        prevX = x
    
    buf1 = [set() for _ in range(BUFSIZE)]
    for x, y, k in XYs2:
        nodes = search(buf1, 0, WIDTH, 0, 0, y-1)
        if nodes:
            for k2 in nodes:
                union(k, k2)
        else:
            update(buf1, y, set([k]))
        prevX = x
     
    for i in range(N):
        get_root(i)
    
    ct = Counter(parent)
    for i in range(N):
        print(ct[parent[i]])

main()


Fixed submission:
from bisect import bisect_left
from collections import Counter
import sys

def main():
    input = sys.stdin.readline
    N = int(input().rstrip())
    # Union-Find
    parent = list(range(N))
    rank = [1] * N
    def get_root(node):
      if parent[node] == node:
        return node
      root = get_root(parent[node])
      parent[node] = root
      return root
    
    def union(a, b):
      root_a = get_root(a)
      root_b = get_root(b)
      if root_a == root_b:
        return
      rank_a = rank[root_a]
      rank_b = rank[root_b]
      if rank_a < rank_b:
        parent[root_a] = root_b
      else:
        parent[root_b] = root_a
        if rank_a == rank_b:
          rank[root_a] += 1

    XYs = []
    XYs1 = []
    XYs2 = []
    for i in range(N):
        x, y = map(int, input().rstrip().split())
        XYs.append([x, y, i])
        XYs2.append([N-x, N-y, i])
    XYs1 = sorted(XYs)
    XYs2.sort()
    
    buf = []
    L = 0
    for x, y, k in XYs1:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1
    
    buf = []
    L = 0
    for x, y, k in XYs2:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1

    ct = Counter()
    for i in range(N):
        ct[get_root(i)] += 1
    
    for p in parent:
        print(ct[p])

main()

Buggy python submission (verdict: Time Limit Exceeded):
from bisect import bisect_left
from collections import Counter

N = int(input())
# Union-Find
parent = [i for i in range(N)]
rank = [1] * N
def get_root(node):
  global parent
  if parent[node] == node:
    return node
  root = get_root(parent[node])
  parent[node] = root
  return root

def union(a, b):
  global parent
  global rank
  root_a = get_root(a)
  rank_a = rank[root_a]
  root_b = get_root(b)
  rank_b = rank[root_b]
  if root_a == root_b:
    return
  if rank_a < rank_b:
    parent[root_a] = root_b
  else:
    parent[root_b] = root_a
    if rank_a == rank_b:
      rank[root_a] += 1

def main():
    XYs = []
    XYs2 = []
    for i in range(N):
        x, y = map(int, input().split())
        XYs.append([x, y, i])
        XYs2.append([N-x, N-y, i])
    XYs.sort()
    XYs2.sort()
    
    BL = (200001).bit_length()
    WIDTH = pow(2, BL)
    BUFSIZE = pow(2, BL+1) - 1
    BASE = BUFSIZE - WIDTH
     
    def update(buf, i, x):
        buf[BASE + i] = x
        i += BASE
        i = (i-1) // 2
        while i >= 0:
            buf[i] = compare(buf[2*i+1], buf[2*i+2])
            i = (i-1) // 2
     
    # [q_left, q_right]
    def search(buf, l, width, i, q_left, q_right):
        if q_right < l or l + width - 1 < q_left:
            return set()
        if q_left <= l and l + width - 1 <= q_right:
            return buf[i]
        nwidth = width // 2
        c1 = search(buf, l, nwidth, 2*i+1, q_left, q_right)
        c2 = search(buf, l+nwidth, nwidth, 2*i+2, q_left, q_right)
        return compare(c1, c2)
     
    def compare(c1, c2):
        if not c1:
            return c2
        if not c2:
            return c1
        return c1 | c2
     
    buf1 = [set() for _ in range(BUFSIZE)]
    prevX = None
    for x, y, k in XYs:
        nodes = search(buf1, 0, WIDTH, 0, 0, y-1)
        if nodes:
            for k2 in nodes:
                union(k, k2)
        else:
            update(buf1, y, set([k]))
        prevX = x
    
    buf1 = [set() for _ in range(BUFSIZE)]
    for x, y, k in XYs2:
        nodes = search(buf1, 0, WIDTH, 0, 0, y-1)
        if nodes:
            for k2 in nodes:
                union(k, k2)
        else:
            update(buf1, y, set([k]))
        prevX = x
     
    for i in range(N):
        get_root(i)
    
    ct = Counter(parent)
    for i in range(N):
        print(ct[parent[i]])

main()


Fixed submission:
from bisect import bisect_left
from collections import Counter
import sys

def main():
    input = sys.stdin.readline
    N = int(input().rstrip())
    # Union-Find
    parent = list(range(N))
    rank = [1] * N
    def get_root(node):
      if parent[node] == node:
        return node
      root = get_root(parent[node])
      parent[node] = root
      return root
    
    def union(a, b):
      root_a = get_root(a)
      root_b = get_root(b)
      if root_a == root_b:
        return
      rank_a = rank[root_a]
      rank_b = rank[root_b]
      if rank_a < rank_b:
        parent[root_a] = root_b
      else:
        parent[root_b] = root_a
        if rank_a == rank_b:
          rank[root_a] += 1

    XYs = []
    XYs1 = []
    XYs2 = []
    for i in range(N):
        x, y = map(int, input().rstrip().split())
        XYs.append([x, y, i])
        XYs2.append([N-x, N-y, i])
    XYs1 = sorted(XYs)
    XYs2.sort()
    
    buf = []
    L = 0
    for x, y, k in XYs1:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1
    
    buf = []
    L = 0
    for x, y, k in XYs2:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1

    ct = Counter()
    for i in range(N):
        ct[get_root(i)] += 1
    
    for p in parent:
        print(ct[p])

main()

Buggy python submission (verdict: Time Limit Exceeded):
from bisect import bisect_left
from collections import Counter

N = int(input())

# Union-Find
parent = [i for i in range(N)]
rank = [1] * N
def get_root(node):
  global parent
  if parent[node] == node:
    return node
  root = get_root(parent[node])
  parent[node] = root
  return root

def union(a, b):
  global parent
  global rank
  root_a = get_root(a)
  rank_a = rank[root_a]
  root_b = get_root(b)
  rank_b = rank[root_b]
  if root_a == root_b:
    return
  if rank_a < rank_b:
    parent[root_a] = root_b
  else:
    parent[root_b] = root_a
    if rank_a == rank_b:
      rank[root_a] += 1

XYs = []
XYs2 = []
for i in range(N):
    x, y = map(int, input().split())
    XYs.append([x, y, i])
    XYs2.append([N-x, N-y, i])
XYs.sort()
XYs2.sort()

BL = (200001).bit_length()
WIDTH = pow(2, BL)
BUFSIZE = pow(2, BL+1) - 1
BASE = BUFSIZE - WIDTH
 
def update(buf, i, x):
    buf[BASE + i] = x
    i += BASE
    i = (i-1) // 2
    while i >= 0:
        buf[i] = compare(buf[2*i+1], buf[2*i+2])
        i = (i-1) // 2
 
# [q_left, q_right]
def search(buf, l, width, i, q_left, q_right):
    if q_right < l or l + width - 1 < q_left:
        return set()
    if q_left <= l and l + width - 1 <= q_right:
        return buf[i]
    nwidth = width // 2
    c1 = search(buf, l, nwidth, 2*i+1, q_left, q_right)
    c2 = search(buf, l+nwidth, nwidth, 2*i+2, q_left, q_right)
    return compare(c1, c2)
 
def compare(c1, c2):
    if not c1:
        return c2
    if not c2:
        return c1
    return c1 | c2
 
buf1 = [set() for _ in range(BUFSIZE)]
prevX = None
for x, y, k in XYs:
    nodes = search(buf1, 0, WIDTH, 0, 0, y-1)
    if nodes:
        for k2 in nodes:
            union(k, k2)
    else:
        update(buf1, y, set([k]))
    prevX = x

buf1 = [set() for _ in range(BUFSIZE)]
for x, y, k in XYs2:
    nodes = search(buf1, 0, WIDTH, 0, 0, y-1)
    if nodes:
        for k2 in nodes:
            union(k, k2)
    else:
        update(buf1, y, set([k]))
    prevX = x
 
for i in range(N):
    get_root(i)

ct = Counter(parent)
for i in range(N):
    print(ct[parent[i]])


Fixed submission:
from bisect import bisect_left
from collections import Counter
import sys

def main():
    input = sys.stdin.readline
    N = int(input().rstrip())
    # Union-Find
    parent = list(range(N))
    rank = [1] * N
    def get_root(node):
      if parent[node] == node:
        return node
      root = get_root(parent[node])
      parent[node] = root
      return root
    
    def union(a, b):
      root_a = get_root(a)
      root_b = get_root(b)
      if root_a == root_b:
        return
      rank_a = rank[root_a]
      rank_b = rank[root_b]
      if rank_a < rank_b:
        parent[root_a] = root_b
      else:
        parent[root_b] = root_a
        if rank_a == rank_b:
          rank[root_a] += 1

    XYs = []
    XYs1 = []
    XYs2 = []
    for i in range(N):
        x, y = map(int, input().rstrip().split())
        XYs.append([x, y, i])
        XYs2.append([N-x, N-y, i])
    XYs1 = sorted(XYs)
    XYs2.sort()
    
    buf = []
    L = 0
    for x, y, k in XYs1:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1
    
    buf = []
    L = 0
    for x, y, k in XYs2:
        idx = bisect_left(buf, [-y, k])
        if idx == L:
            buf.append([-y, k])
        else:
            ny, nk = buf[-1]
            while L > idx:
                ty, tk = buf.pop()
                union(k, tk)
                L -= 1
            buf.append([ny, nk])
        L += 1

    ct = Counter()
    for i in range(N):
        ct[get_root(i)] += 1
    
    for p in parent:
        print(ct[p])

main()