Skip to content

10000. 원 영역

TLDR#

뭔가 정렬을 한 뒤에 스택으로 풀었던 것 같은데 원이 끝나는 지점을 중심으로 정렬하고 새로 탐색한 원이 기존의 원들을 덮어버리는 경우에 따라서 영역의 수를 하나 더 카운트하고 스택을 비워버리는 방식이었던 것 같다.


Snippet#

"""
http://boj.kr/10000
"""

from collections.abc import Generator, Iterable, Sequence
from sys import stdin

type centerx = int
type radius = int
type area_cnt = int
type leftx = int
type rightx = int


def input() -> str:
    return stdin.readline().strip()


def main(circles: Iterable[tuple[centerx, radius]]) -> area_cnt:
    """
    서로 접할 수 있지만 교차하지 않는 circle이 주어졌을 때, 원들로 만들어지는
    영역의 수를 구하라
    """
    # circles를 원들이 출발하는 지점과 끝나는 지점으로 변환하고 끝나는 지점을
    # 기준으로 정렬하라
    _circles: Sequence[tuple[leftx, rightx]] = sorted(
        map(lambda tup: (tup[0] - tup[1], tup[0] + tup[1]), circles),
        # right를 기준으로 1차 정렬하고, 만약 같을 경우, left를 기준으로
        # **역순**으로 정렬해야 하기 때문에 음수를 붙였다.
        # left를 역순으로 정렬해야 하는 이유는 내부 원을 다 읽은 다음에
        # 외부 원을 읽어야 하기 때문.
        key=lambda tup: (tup[1], -tup[0]),
    )
    cnt = 1

    stack: list[tuple[leftx, rightx]] = []
    for left, right in _circles:
        # TOP을 새 원이 감싸게 되는 경우, 내부에 싸여진 원들을 하나씩 pop한다.
        # 이때 내부 원들이 외부 원을 완벽히 나누는지 확인해야 한다.
        diameter = 0
        while len(stack) > 0 and left <= stack[-1][0]:
            popped = stack.pop()
            diameter += popped[1] - popped[0]

        if diameter == right - left:
            # 내부 원들이 외부 원을 완벽히 나눈다
            cnt += 1

        stack.append((left, right))
        cnt += 1  # 이건 원 그 자체로 만든 영역

    return cnt


if __name__ == "__main__":
    DEBUG = False

    n = int(input())

    def circle_reader(n: int) -> Generator[tuple[centerx, radius], None, None]:
        for _ in range(n):
            c, r = map(int, input().split())
            yield c, r

    circles = circle_reader(n)

    print(main(circles))

Sample Input & Expected Output#

Input#


Expected Output#



Notes#