Pokedex

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

요약
정렬, 필터, 커서 명령을 처리하며 포켓몬 도감 데이터베이스를 관리하고 flush 때 격자를 출력한다.
난이도

어려움10점 중 8점

유형
정렬, 구현, 시뮬레이션, 배열
정답자
아직 제출이 없습니다

문제

여러분은 포켓몬학의 권위자 오박사님의 연구소의 연구원으로서 새로운 포켓몬 도감을 제작하는 임무를 맡게 되었다. 포켓몬 도감은 사용자가 입력한 커맨드에 따라 조건에 맞는 포켓몬을 화면에 표시하는 도구다. 현재 도감에는 총 NN종류의 포켓몬이 수록되어 있으며, 각 포켓몬마다 도감 번호, 이름, 1타입, 2타입, 체력, 공격, 방어, 특수공격, 특수방어, 스피드가 도감의 데이터베이스에 저장되어 있다.

  • 도감 번호는 11 이상 NN 이하의 정수다. 각 포켓몬의 도감 번호는 서로 다르다.

  • 이름은 영소문자로만 이루어진 길이 1 이상 12 이하의 문자열이다. 각 포켓몬의 이름은 서로 다르다.

  • 1타입은 bug, dark, dragon, electric, fairy, fighting, fire, flying, ghost, grass, ground, ice, normal, poison, psychic, rock, steel, water 중 하나의 문자열이다.

  • 2타입은 bug, dark, dragon, electric, fairy, fighting, fire, flying, ghost, grass, ground, ice, normal, poison, psychic, rock, steel, water, none 중 1타입과는 다른 하나의 문자열이다.

  • 체력, 공격, 방어, 특수공격, 특수방어, 스피드는 각각 11 이상 200,000200\\, 000 이하의 정수다.

도감의 화면은 가로로 WW칸, 세로로 HH칸의 그리드 형태이며, 한 칸에 하나의 포켓몬을 표시할 수 있다. 여러분이 제작해야 하는 커맨드는 다음과 같다. <a|b|c>는 a, b, c 중 하나의 문자열이 입력됨을, valval은 정수가 입력됨을, strstr은 문자열이 입력됨을 의미한다. 이외에는 주어진 문자열이 그대로 커맨드로 입력된다.

  • sort <idx|hp|atk|def|special_atk|special_def|speed> <asc|desc>

    정렬 기준을 <도감 번호 | 체력 | 공격 | 방어 | 특수공격 | 특수방어 | 스피드> 수치의 <오름차순 | 내림차순> 으로 변경한다.

    • 두 포켓몬의 제시한 정렬 기준에 대한 수치가 같을 경우, 해당 sort 커맨드 입력 직전의 정렬 순서에 따라 정렬한다.

    • 초기 상태에서 정렬 기준은 도감 번호의 오름차순이다.

  • filter <idx|hp|atk|def|special_atk|special_def|speed> <min|max> valval

    필터링 조건 중, 화면에 표시할 포켓몬의 <도감 번호 | 체력 | 공격 | 방어 | 특수공격 | 특수방어 | 스피드>의 <하한 | 상한>을 valval로 수정한다. valval은 11 이상 200,000200\\, 000 이하의 정수다.

    • 초기 상태에서 모든 하한은 11, 상한은 200,000200\\, 000으로 설정되어 있다.
  • filter name strstr

    필터링 조건 중, 화면에 표시할 포켓몬의 이름의 접두사를 strstr로 수정한다. strstr은 영소문자로만 이루어진 길이 1 이상 12 이하의 문자열 또는 BLANK다. BLANK는 빈 문자열을 의미한다.

    • 초기 상태에서 접두사는 빈 문자열로 설정되어 있다.
  • filter type <bug|dark|dragon|electric|fairy|fighting|fire|flying|ghost|grass|ground|ice|normal|poison|psychic|rock|steel|water>

    필터링 조건 중, 화면에 표시할 포켓몬의 타입의 집합 TT를 수정한다.

    • 입력한 타입이 TT에 존재하는 경우, 해당 타입을 TT에서 제거한다.

    • 입력한 타입이 TT에 존재하지 않는 경우, 해당 타입을 TT에 추가한다.

    • 초기 상태에 TT는 18개의 원소 bug, dark, dragon, electric, fairy, fighting, fire, flying, ghost, grass, ground, ice, normal, poison, psychic, rock, steel, water로 이루어져 있다.

  • 어떤 포켓몬이 필터링 조건을 만족함은 다음을 의미한다.

    • 이 포켓몬의 도감 번호, 체력, 공격, 방어, 특수공격, 특수방어, 스피드가 각각 설정된 하한 이상 상한 이하다.

    • 이 포켓몬의 이름의 접두사가 필터링 조건으로 설정된 접두사와 일치한다. 또는 필터링 조건으로 설정된 접두사가 빈 문자열이다.

    • 이 포켓몬의 1타입과 2타입 중 화면에 표시할 포켓몬의 타입의 집합 TT의 원소와 일치하는 것이 적어도 하나 존재한다.

  • resize <W|H> valval

    도감 화면의 그리드 크기를 나타내는 값 <WW|HH>를 valval로 변경한다. valval은 11 이상 1010 이하의 정수다.

    • 초기 상태에서 WW, HH는 각각 55다.
  • cursor <l|r|u|d>

    커서를 움직인다. 커서는 도감 내에서 특정 포켓몬을 가리키는 역할을 한다.

    • 초기 상태에서 커서는 도감 번호 1번 포켓몬을 가리킨다.

    • sort 또는 filter 커맨드를 처리한 직후, 커서는 필터링 조건을 만족하는 포켓몬 중 정렬 기준상 맨 앞에 있는 포켓몬으로 이동한다.

    • 필터링 조건을 만족하는 포켓몬이 없는 상태면 커서는 대신 NULL을 가리킨다. NULL은 포켓몬이 아님에 유의하라.

    • cursor l 필터링 조건을 만족하는 포켓몬 중, 현재 정렬 기준상에서 커서가 가리키는 포켓몬 직전의 포켓몬으로 커서를 이동시킨다. 그런 포켓몬이 없는 경우, 필터링을 만족하는 포켓몬 중 정렬 기준상 맨 앞에 있는 포켓몬으로 커서를 이동시킨다.

    • cursor r 필터링 조건을 만족하는 포켓몬 중, 현재 정렬 기준상에서 커서가 가리키는 포켓몬 직후의 포켓몬으로 커서를 이동시킨다. 그런 포켓몬이 없는 경우, 필터링을 만족하는 포켓몬 중 정렬 기준상 맨 뒤에 있는 포켓몬으로 커서를 이동시킨다.

    • cursor u 필터링 조건을 만족하는 포켓몬 중, 현재 정렬 기준상에서 커서가 가리키는 포켓몬 WW개 전의 포켓몬으로 커서를 이동시킨다. 그런 포켓몬이 없는 경우, 필터링을 만족하는 포켓몬 중 정렬 기준상 맨 앞에 있는 포켓몬으로 커서를 이동시킨다.

    • cursor d 필터링 조건을 만족하는 포켓몬 중, 현재 정렬 기준상에서 커서가 가리키는 포켓몬 WW개 후의 포켓몬으로 커서를 이동시킨다. 그런 포켓몬이 없는 경우, 필터링을 만족하는 포켓몬 중 정렬 기준상 맨 뒤에 있는 포켓몬으로 커서를 이동시킨다.

  • flush

    현재 필터링 조건, 정렬 기준, 커서의 위치에 맞는 도감 화면의 상태를 출력한다. 화면의 상태를 출력하는 방법은 다음과 같다.

    • 화면상의 모든 칸을 빈칸으로 설정한다.

    • 필터링 조건을 만족하는 포켓몬들을 정렬 기준에 맞게 나열한 뒤 앞에서부터 WW개씩 묶는다. 남은 포켓몬이 WW개 미만이라면 모두 묶는다. 그 뒤 커서가 가리키는 포켓몬이 포함된 묶음부터 정렬 순서대로, 화면의 맨 위 가로줄부터 순서대로 내려가며 표시한다. 각 가로줄에 포켓몬을 표시할 때는 해당 묶음에서 정렬 순서대로 왼쪽 칸부터 채운다. 만약 커서가 가리키는 포켓몬이 포함된 묶음부터 세었을 때 묶음이 HH개를 초과한다면, 그중 앞에서부터 HH개의 묶음만 표시한다.

      • 커서가 NULL을 가리키고 있다면 해당 과정을 건너뛴다.
    • 화면의 상태는 HH개의 줄로 표현되고, 각 줄에는 WW개의 정수를 공백으로 구분해 출력한다. 그중 ii번째 줄의 jj번째 정수는 화면상에서 위에서부터 ii번째 가로줄의 왼쪽에서부터 jj번째 칸에 표시된 포켓몬의 도감 번호다. 만약 해당 칸이 비어 있다면 0을 출력한다.

곧 오박사님이 연구소로 돌아오신다. 그전까지 포켓몬 도감을 완성하고 칼퇴의 꿈을 이뤄보자!

입력

첫째 줄에 포켓몬의 종류를 나타내는 정수 NN이 주어진다. (1≤N≤200,0001\le N\le 200\\, 000)

그다음 줄부터 NN개의 줄에 걸쳐 각 포켓몬의 정보가 공백으로 구분되어 주어진다. 그중 ii번째 줄에는 도감 번호 ii번에 해당하는 포켓몬의 정보가 이름, 1타입, 2타입, 체력, 공격, 방어, 특수공격, 특수방어, 스피드 순으로 주어진다.

그다음 줄에 입력할 커맨드의 수 QQ가 주어진다. (1≤Q≤200,0001\le Q\le 200\\, 000)

그다음 줄부터 QQ개의 줄에 걸쳐 커맨드가 한 줄에 하나씩 주어진다. 이때, flush 커맨드는 1번 이상 10번 이하로 주어진다. 마지막 커맨드는 반드시 flush다.

출력

flush 커맨드가 주어질 때마다 그때의 화면 상태를 출력한다. 각 화면 상태 사이에는 빈 줄 하나를 출력한다.

힌트

입출력의 양이 많으므로, 빠른 입출력을 사용하는 것을 권장합니다. 다음은 대표적인 언어에서 빠른 입출력을 이용하는 방법입니다.

  • C++: cin, cout을 사용한다면 main 함수 첫 줄에 std::cin.tie(0); std::cout.tie(0); std::ios::sync_with_stdio(false);를 추가하고, 줄바꿈 시 endl 대신 '\n'을 출력해주세요. 이 경우 scanf를 비롯한 C의 입출력 함수는 사용할 수 없음에 유의해 주세요.
    • scanf/printf는 충분히 빠르므로 별도의 처리를 하지 않아도 괜찮습니다.
  • Java: Scanner와 System.out.println 대신 BufferedReader와 BufferedWriter를 사용해 주세요.
  • Python3, PyPy3: input() 대신 sys.stdin.readline().rstrip()을 사용해 주세요.

예제1

  1. 예제 1

    입력
    9
    bulbasaur grass poison 45 49 49 65 65 45
    ivysaur grass poison 60 62 63 80 80 60
    venusaur grass poison 80 82 83 100 100 80
    charmander fire none 39 52 43 60 50 65
    charmeleon fire none 58 64 58 80 65 80
    charizard fire flying 78 84 78 109 85 100
    squirtle water none 44 48 65 50 64 43
    wartortle water none 59 63 80 65 80 58
    blastoise water none 79 83 100 85 105 78
    14
    flush
    sort atk desc
    filter type fire
    flush
    filter type fire
    cursor d
    resize W 2
    cursor l
    flush
    cursor l
    flush
    sort speed asc
    resize H 4
    flush
    
    예상 출력
    1 2 3 4 5
    6 7 8 9 0
    0 0 0 0 0
    0 0 0 0 0
    0 0 0 0 0
    
    6 9 3 8 2
    1 7 0 0 0
    0 0 0 0 0
    0 0 0 0 0
    0 0 0 0 0
    
    8 2
    4 1
    7 0
    0 0
    0 0
    
    3 5
    8 2
    4 1
    7 0
    0 0
    
    7 1
    8 2
    4 9
    3 5