사용자 도구

사이트 도구


ps:problems:boj:32374

선물 고르기

ps
링크acmicpc.net/…
출처BOJ
문제 번호32374
문제명선물 고르기
레벨골드 4
분류

그리디

시간복잡도O(n)
인풋사이즈n<=200000
사용한 언어Python 3.13
제출기록81084KB / 296ms
최고기록296ms
해결날짜2025/02/28

풀이

  • 상황을 정리해보면 답은 굉장히 간단하다. 내 상자 크기보다 작은 선물 중에서 가장 큰 것이 답이다.
  • 우선, 상자와 선물이 다 정렬되어있다고 생각하자
    • B[0]>=B[1]>=B[2]>= … >= B[N-1]
    • A[0]>=A[1]>=A[2]>= … >= A[N-1]
  • 모든 선물을 모든 상자에 넣을 수 있는 방법이 최소 한가지는 있다. 그렇다면, 적어도, 상자와 선물을 순위대로 매칭했을때는 선물들이 상자에 모두 들어갈수 있어야 한다. 다시 말하면 B[0]>=A[0], B[1]>=A[1], …, B[N-1]>=A[N-1] 이다
  • 이제 내 차례에 i번 상자를 고르게 되는 상황이라 하자. 이 말은 앞선 K명이 상자를 가져가는 동안 0번부터 i-1번 상자를 다 가져가버렸다는 말이다. i번 상자에 들어갈 수 있는 가장 큰 선물의 번호가 j번이라고 하자 (A[j-1]>B[i]>=A[j]). 0번부터 i-1번 상자들에 다음과 같이 선물이 담겨있었다면, i번째 상자에 j번 선물이 들어있을 수 있다.
    • j번 상자보다 큰 상자들에는 같은 순위의 선물들이 들어있었고, j번부터 i-1번까지의 상자들에는 한 순위 더 작은 선물이 담겨있었다면, j번 선물과 i번 상자가 남아 있을 것이다.
    • B[0]>=A[0], B[1]>=A[1], …, B[j-1]>=A[j-1] 이고 B[j]>=A[j+1], …., B[i-1]⇒A[i] 이므로 가능하다
    • 이제 B[i] ⇒ A[j] 이므로 i번 상자에 j번 선물을 담으면 된다.
  • 나머지 선물과 상자들은 다시 크기 순서대로 매칭됐다고 생각하면 된다
  • 결국, 내가 선택하게 되는 선물상자의 크기가 얼마인지, 그리고 그 상자안에 들어갈수 있는 가장 큰 선물이 무엇인지만 찾으면 된다.
  • 둘다 그냥 O(n)에 찾을 수 있다. 태그에는 이분탐색이나 BST 가 포함되어 있는데, 아마도 상자안에 들어갈 수 있는 가장 큰 선물이 무엇인지를 찾기 위해서 정렬후 이분탐색이나 BBST등을 사용해야 한다고 생각한것 같다. 그러나, 단 한번의 쿼리만 처리하면 되기 때문에 그냥 모든 원소를 훑으면서 O(n)에 찾으면 충분하다.

코드

"""Solution code for "BOJ 32374. 선물 고르기".

- Problem link: https://www.acmicpc.net/problem/32374
- Solution link: http://www.teferi.net/ps/problems/boj/32374
"""

import collections
import sys


def main():
    # pylint: disable-next=unused-variable
    N, K = [int(x) for x in sys.stdin.readline().split()]
    A = [int(x) for x in sys.stdin.readline().split()]
    B = [int(x) for x in sys.stdin.readline().split()]
    C = [int(x) for x in sys.stdin.readline().split()]

    counter = collections.Counter(B)
    counter.subtract(C)
    box = max(+counter)
    answer = max(a_i for a_i in A if a_i <= box)

    print(answer)


if __name__ == '__main__':
    main()

토론

댓글을 입력하세요:
K N I N X
 
ps/problems/boj/32374.txt · 마지막으로 수정됨: 2025/03/01 08:01 저자 teferi