가방에 최대한 가격이 높은 보석을 담았을 때 얻을 수 있는 보석 가격의 합을 구하는 문제이다.
한 가방에는 오직 하나의 보석만 들어갈 수 있다.
N(보석의 수), K(가방의 수)의 최대 값이 각각 300,000으로, O(N * K)
의 이중 for loop만 돌아도 시간 초과가 발생할 수 있다.
O((N+K)*logN)
의 시간복잡도로 문제를 해결할 수 있다.pop
연산을 수행했을 때 첫번째나 마지막에 있는 값을 빼는 것이 아니라, 우선순위가 가장 높은 값을 뺄 수 있는 자료구조를 말한다.# 무게가 무거운 순으로 정렬
jewels = [tuple(map(int, input().split())) for _ in range(N)]
jewels.sort(key = lambda x : x[0], reverse = True)
# 무거운 가방 순으로 정렬
bags = [int(input()) for _ in range(K)]
bags.sort(reverse = True)
pop
연산을 했을 때 가벼운 것부터 순차적으로 꺼내기 위함이다.# 우선순위 큐 (max heapque)
hq = []
heappush
함수를 통해 힙 자료구조가 될 것이므로 그냥 빈 리스트를 선언하면 된다.while bags:
# 가장 가벼운 가방을 꺼냄
bag = bags.pop()
while jewels:
# 현재 가장 가벼운 보석을 꺼냄
weight, value = jewels.pop()
if bag >= weight:
# 가방에 넣을 수 있다면 최대힙에 추가
heapq.heappush(hq, -value)
else:
# 넣을 수 없다면 다시 보석 리스트에 추가하고 탐색 종료
jewels.append((weight, value))
break
heappush
하면 절대값이 큰 것부터 빼오는 최대힙을 만들 수 있다.heappop
연산을 수행했을 때, 가장 높은 가격의 음수 값이 반환된다. 즉 높은 가격이 높은 우선순위가 되는 우선순위 큐를 구현한 것이다.# 최대힙에서 heappop 한 값을 답변에 더함
if hq:
answer -= heapq.heappop(hq)
heappop
된 값을 정답 변수에 더해주면 된다.pop
하면 IndexError 발생)N=3 K=2
jewels = [(1, 65), (5, 23), (2, 99)]
bags = [10, 2]
answer = 0
hq = []
jewels = [(5, 23), (2, 99), (1, 65)]
bags = [10, 2]
answer = 0
hq = []
jewels = [(5, 23), (2, 99), (1, 65)]
bags = [10]
answer = 0
bag = 2
hq = []
jewels = [(5, 23), (2, 99)]
bags = [10]
answer = 0
bag = 2
hq = [-65]
jewels = [(5, 23)]
bags = [10]
answer = 0
bag = 2
hq = [-99, -65] # 편의상 정렬된 리스트 형태로 표현
jewels = [(5, 23)]
bags = [10]
answer = 99
bag = 2
hq = [-65] # 편의상 정렬된 리스트 형태로 표현
jewels = [(5, 23)]
bags = []
answer = 99
bag = 10
hq = [-65] # 편의상 정렬된 리스트 형태로 표현
jewels = []
bags = []
answer = 99
bag = 10
hq = [-65, -23] # 편의상 정렬된 리스트 형태로 표현
jewels = []
bags = []
answer = 164
bag = 10
hq = [-23] # 편의상 정렬된 리스트 형태로 표현
import sys
import heapq
input = sys.stdin.readline
N, K = map(int, input().split())
jewels = []
bags = []
length = N
answer = 0
# 무게가 무거운 순으로 정렬
jewels = [tuple(map(int, input().split())) for _ in range(N)]
jewels.sort(key = lambda x : x[0], reverse = True)
# 무거운 가방 순으로 정렬
bags = [int(input()) for _ in range(K)]
bags.sort(reverse = True)
# 우선순위 큐 (max heapque)
hq = []
while bags:
# 가장 가벼운 가방을 꺼냄
bag = bags.pop()
while jewels:
# 현재 가장 가벼운 보석을 꺼냄
weight, value = jewels.pop()
if bag >= weight:
# 가방에 넣을 수 있다면 최대힙에 추가
heapq.heappush(hq, -value)
else:
# 넣을 수 없다면 다시 보석 리스트에 추가하고 탐색 종료
jewels.append((weight, value))
break
# 최대힙에서 heappop 한 값을 답변에 더함
if hq:
answer -= heapq.heappop(hq)
print(answer)
우선순위 큐에 대한 개념을 몰래 이분 탐색으로 풀려다가 시간초과로 한창 끙끙 댔다.
힙을 이용해 큐에서 꺼내는 순서를 원하는 대로 커스터마이징할 수 있다는 것을 잘 기억해두어야 겠다.
힙 구조에서는 pop, push 연산 모두 시간복잡도 O(log n)이라는 것도 기억해두자.
안녕하세요. 이번 문제에 대한 질문이 있습니다.
O((N+K)logN) 의 시간복잡도면 60만 547 = 328,200,000 인데요..
1초에 1억번 정도의 연산을 수행하는걸로 알고 있는데, 이거 시간초과 왜 안날까요?