만드는 중입니다

아직 만드는 중이라 바뀔 수 있습니다

Python 코드 접기

시간 제한2초메모리 제한1024 MB

요약
올바른 파이썬 코드에서 블록을 접거나 펼치는 쿼리를 처리하고, 출력 쿼리마다 보이는 줄 수를 구합니다.
난이도

보통10점 중 6점

유형
트리, 세그먼트 트리, DFS
정답자
아직 제출이 없습니다

섹션 1

Python은 간결하고 가독성이 높은 고급 프로그래밍 언어이다. 데이터 분석, 인공지능, 웹 개발 등 다양한 분야에서 널리 쓰이며, 커뮤니티와 생태계가 풍부하다.

Python 코드는 다음 요소로 이루어진다.

  • 라인 (Line)은 Python 코드의 한 행이다. 이 문제에서 각 라인은 헤더 또는 심플문 중 하나이다.
  • 블록 (Block)은 반복문과 조건문 등을 구성한다. 여러 라인으로 이루어지며 헤더와 바디로 나뉜다.
  • 블록을 구분하기 위해 각 라인 앞에 0개 이상의 탭 문자를 넣는다. 이 탭 문자를 인덴트 (Indent)라고 부르고, 라인 앞에 있는 탭 문자의 개수를 인덴트 레벨 (Indent Level)이라고 한다. 이 문제의 모든 예시에서는 탭 문자를 공백 문자 4개로 표기한다.
  • 헤더 (Header)는 블록을 시작하는 부분이며, 정확히 한 라인으로 이루어진다.
  • 심플문 (Simple Statement)은 라인 중 헤더가 아닌 것이다.
  • 바디 (Body)는 블록의 안쪽 부분이며, 1라인 이상으로 이루어진다.

올바른 Python 코드는 다음 조건 중 적어도 하나를 만족한다.

  • 인덴트 레벨이 0인 심플문으로만 이루어진 코드이다.
  • 인덴트 레벨이 0인 헤더로 시작하며, 헤더 아래에 1라인 이상의 코드가 있다. 헤더를 제거하고 남은 라인들의 인덴트 레벨을 모두 1씩 줄이면 올바른 Python 코드가 된다. 이때 이 코드는 블록이 되고, 헤더를 제외한 나머지 코드는 모두 블록의 바디가 된다.
  • 올바른 Python 코드 두 개를 이어 붙인 코드이다.

올바르지 않은 Python 코드의 예시와 그 이유는 다음과 같다.

a=1
    b=3
c=5

심플문으로만 구성되어 있지만, 인덴트 레벨이 모두 0은 아니다.

for i in range(n):
for x in a:
    print(s)

첫 번째 블록의 바디에 1라인 이상의 코드가 없다.

for i in range(n):
        for j in range(n):
            print(i+j)

첫 번째 라인이 헤더이지만, 헤더를 제거하고 인덴트 레벨을 1씩 줄여도 올바른 코드가 되지 않는다.

다음은 사용자에게서 정수 nn을 입력받아 문자 '*'로 이루어진 직각삼각형을 출력하는 올바른 Python 코드의 예시이다.

1| n = int(input())
2| a = []
3| for i in range(1, n+1):
4|     s = ""
5|     for j in range(i):
6|         s += "*"
7|     a.append(s)
8| for s in a:
9|     print(s)

많은 코드 에디터가 Code Folding 기능을 제공한다. 이 기능은 블록의 바디를 숨기고 헤더만 보여 주어, 긴 코드를 읽기 편하게 한다. 엄밀하게 정의하면 다음과 같다.

처음에는 모든 블록이 펼쳐진 상태이다. 코드에 블록이 있으면 Code Folding 기능으로 그 블록을 접거나 펼 수 있다. 블록을 접으면 그 블록의 바디에 속한 라인은 모두 보이지 않는다. 또한, 그 블록을 포함하는 다른 블록을 접더라도 안쪽 블록의 접힌 상태는 유지된다.

예를 들어, 위 코드의 두 번째 블록을 접으면 6번 라인이 보이지 않는다.

1| n = int(input())
2| a = []
3| for i in range(1, n+1):
4|     s = ""
5|     for j in range(i): ...
7|     a.append(s)
8| for s in a:
9|     print(s)

이어서 첫 번째 블록을 접으면 4번, 5번, 6번, 7번 라인이 보이지 않는다.

1| n = int(input())
2| a = []
3| for i in range(1, n+1): ...
8| for s in a:
9|     print(s)

첫 번째 블록을 다시 펼쳐도 두 번째 블록은 접힌 상태가 그대로 유지되므로, 6번 라인은 여전히 보이지 않는다.

올바른 Python 코드가 주어졌을 때, Code Folding 기능을 수행하고 각 쿼리 이후에 보이는 코드의 라인 개수를 출력하는 프로그램을 작성하라.

입력

첫 번째 줄에 코드의 라인 수 NN과 쿼리의 개수 QQ가 주어진다. (2≤N≤500 000(2 \leq N \leq 500\,000, 1≤Q≤500 000)1 \leq Q \leq 500\,000)

두 번째 줄부터 NN개의 줄에 걸쳐 전체 코드에 대한 정보가 주어진다. ii번째 줄에는 정수 LiL_i와 알파벳 소문자 TiT_i가 주어진다. ii번째 라인의 인덴트 레벨은 LiL_i이고, TiT_i가 h이면 헤더, s이면 심플문이다. (1≤Li≤N)(1 \leq L_i \leq N)

N+2N+2번째 줄부터 한 줄에 하나씩 총 QQ개의 쿼리가 주어진다.

  • t xx: 접히지 않은 전체 코드에서 xx번째 블록이 펴져 있으면 접고, 접혀 있으면 편다. 상위 블록이 접혀 있어 xx번째 블록이 보이지 않는 경우는 주어지지 않는다. (1≤x≤(1 \leq x \leq 헤더 라인의 총 개수))
  • p: 현재 보이는 코드의 라인 개수를 출력한다. 이 쿼리는 적어도 하나 이상 주어진다.

주어진 코드는 올바른 Python 코드의 조건을 만족함이 보장된다.

출력

주어진 쿼리를 순서대로 실행했을 때, 각 p 쿼리가 주어질 때마다 그 시점에 보이는 라인 개수를 한 줄에 하나씩 출력한다.

예제1

  1. 예제 1

    입력
    9 8
    0 s
    0 s
    0 h
    1 s
    1 h
    2 s
    1 s
    0 h
    1 s
    t 2
    p
    t 1
    p
    t 3
    p
    t 1
    p
    
    예상 출력
    8
    5
    4
    7