[BOJ] 회전 초밥 - 2531 (S1)
[BOJ] 회전 초밥 - 2531 (S1)
| 시간 제한 | 메모리 제한 |
|---|---|
| 1 초 | 256 MB |
문제
회전 초밥 음식점에는 벨트 위에 같은 종류의 초밥이 둘 이상 있을 수 있다.
새로 문을 연 회전 초밥 가게가 손님을 끌기 위해 다음과 같은 이벤트를 한다.
- 벨트의 임의의 한 위치부터 k개의 접시를 연속해서 먹을 경우 할인된 정액 가격으로 제공한다.
- 각 고객에게 초밥의 종류 하나가 쓰인 쿠폰을 발행하고, 1번 행사에 참가할 경우 이 쿠폰에 적혀진 종류의 초밥 하나를 추가로 무료로 제공한다. 만약 이 번호에 적혀진 초밥이 회전 초밥 벨트 위에 없을 경우, 요리사가 새로 만들어 손님에게 제공한다.
위 할인 행사에 참여하여 가능한 한 다양한 종류의 초밥을 먹으려고 한다. 먹을 수 있는 초밥 가짓수의 최댓값을 구하는 프로그램을 작성하시오.
입력
첫 번째 줄에는 회전 초밥 벨트에 놓인 접시의 수 N, 초밥의 가짓수 d, 연속해서 먹는 접시의 수 k, 쿠폰 번호 c가 주어진다. 단, 2 ≤ N ≤ 30,000, 2 ≤ d ≤ 3,000, 2 ≤ k ≤ 3,000 (k ≤ N), 1 ≤ c ≤ d이다.
출력
주어진 회전 초밥 벨트에서 먹을 수 있는 초밥의 최대 가짓수를 출력하시오.
풀이
슬라이딩 윈도우 기법을 사용하는 문제이다.
코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from collections import defaultdict
N, d, k, c = map(int, input().split())
sushi_list = [int(input()) for _ in range(N)]
counter = defaultdict(int)
kind = 0
for i in range(k):
if counter[sushi_list[i]] == 0:
kind += 1
counter[sushi_list[i]] += 1
# 쿠폰
max_kind = kind + (1 if counter[c] == 0 else 0)
for i in range(1, N):
remove = sushi_list[i - 1]
counter[remove] -= 1
if counter[remove] == 0: # 더 이상 없으면 종류 수 감소
kind -= 1
cur = sushi_list[(i + k - 1) % N]
if counter[cur] == 0:
kind += 1
counter[cur] += 1
# 쿠폰
total = kind + (1 if counter[c] == 0 else 0)
max_kind = max(max_kind, total) # 최대 종류 수 갱신
print(max_kind)
시간 복잡도
O(N)
This post is licensed under CC BY 4.0 by the author.