여러개의 쿼리가 주어지는데,
1. 스택의 맨 뒤에 숫자를 추가
2. 스택이 비어있지 않으면 맨 뒤의 원소를 제거
3. 맨 뒤에서부터 최소 몇개의 수를 선택해야, 이들을 mod로 나누었을때 0,1,2,..,mod-1이 최소 1개 이상 나타나는가?
예를 들어 [2,3]인 경우 4로 나누면 나머지는 [2,3]인데, 여기서 0,1이 없으므로 -1
[2,3,1,4]인 경우 4로 나누면 나머지는 [2,3,1,0]인데 여기서 0,1,2,3이 모두 나왔으므로 4
------------------------------------------------------------------------------------------------------------------------------------------------
스택에 숫자를 쌓아나가는데, 핵심은 mod로 나눈 나머지를 쌓아나가고
0,1,2,..,mod-1이 각각 언제 마지막으로 나오는지 인덱스를 저장해둔다
그러면 이 인덱스들의 최솟값을 이용하면 O(mod)만에 3번 쿼리의 정답을 찾을 수 있다
[0,1,2,3,2,1,0,3,1,3,2,1,3] 이렇게 되었을때 mod = 4이면
0은 마지막에 나온 인덱스가 6번
1은 마지막에 나온 인덱스가 11번
2는 마지막에 나온 인덱스가 10번
3은 마지막에 나온 인덱스가 12번
따라서 뒤에서부터 인덱스 6번까지 원소를 선택해야 0,1,2,3이 모두 1번씩 나오게된다
이렇게 하면 1번 쿼리는 O(1)에 넣기만 하면 되는데 0,1,2,..,mod-1값이 어느 인덱스에 나오는지
나올때마다 인덱스를 저장해두면 배열은 마지막 인덱스값을 가지게 된다
from sys import stdin
q,mod = map(int,stdin.readline().split())
A = []
visited = [-1]*mod
for _ in range(q):
Q = stdin.readline().rstrip().split()
if Q[0] == '1':
m = int(Q[1]) % mod
A.append(m)
visited[m] = len(A)-1
2번 쿼리는 원소를 제거하면, 스택을 뒤에서부터 순회해서 제거된 원소가 처음으로 나온 위치를 찾고
마지막으로 나오는 인덱스 위치를 그것으로 갱신하면 된다
mod = 100까지이므로, 그냥 순회해도 괜찮다
elif Q[0] == '2':
if len(A) == 0:
continue
x = A.pop()
find = False
for i in range(len(A)-1,-1,-1):
if A[i] == x:
visited[x] = i
find = True
break
if find == False:
visited[x] = -1
3번 쿼리는 마지막으로 나온 인덱스 위치들의 최솟값을 찾으면
맨 뒤에서부터 거기까지 개수를 세는건 쉽다
그러면 최대 2*10^7에 문제를 해결할 수 있다
else:
i = min(visited)
if i == -1:
print(-1)
else:
print(len(A) - i)
1번 쿼리를 처리할 때 마지막에 나오는 위치를 저장하기 위해 visited의 원소를 배열로 저장해두는 것도 괜찮을듯?
visited[0] = []
visited[1] = []
...
visited[mod-1] = []
이렇게 해두고 매 원소를 저장할때마다 인덱스를 append해두면 마지막 위치에는 마지막에 저장된 위치가 저장
그러면 2번 쿼리를 O(1)에 처리할 수 있을 것
from sys import stdin
q,mod = map(int,stdin.readline().split())
A = []
visited = [[] for _ in range(mod)]
for _ in range(q):
Q = stdin.readline().rstrip().split()
if Q[0] == '1':
m = int(Q[1]) % mod
A.append(m)
visited[m].append(len(A)-1)
elif Q[0] == '2':
if len(A) == 0:
continue
x = A.pop()
visited[x].pop()
else:
no = False
j = len(A)+10
for i in range(mod):
if len(visited[i]) == 0:
no = True
break
else:
if j > visited[i][-1]:
j = visited[i][-1]
if no:
print(-1)
else:
print(len(A) - j)
'알고리즘 > 자료구조(스택,큐,해시맵)' 카테고리의 다른 글
O(N)으로 순서쌍 찾기1 - 기울기가 K인 직선의 개수 (0) | 2025.02.19 |
---|---|
가장 긴 연속하는 올바른 괄호 부분 문자열의 길이 구하는 알고리즘 (0) | 2025.02.17 |
코딩테스트 복기 - 배열에서 특정 수보다 작은 수 중 가장 가까운 수를 찾는 방법(find nearest element than smaller one on the left side) (0) | 2023.05.22 |
[Java]자바로 구현하는 절댓값 우선순위 큐 (0) | 2023.03.22 |
[Java]우선순위 큐 응용 - MN개의 조합에서 조건을 만족하는 k번째 수를 찾는 빠르게 찾는 방법 1편 (0) | 2023.03.21 |