ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 22252번 정보 상인 호석
    Algorithm Study/Python 2021. 8. 24. 02:04

    https://www.acmicpc.net/problem/22252

     

    22252번: 정보 상인 호석

    암흑가의 권력은 주먹과 정보에서 나온다. 주먹은 한 명에게 강하고, 정보는 세계를 가지고 놀 수 있기 때문에 호석이는 세상 모든 정보를 모으는 "정보 상인"이 되고 싶다. 정보 상인은 정보를

    www.acmicpc.net

    문제

    암흑가의 권력은 주먹과 정보에서 나온다. 주먹은 한 명에게 강하고, 정보는 세계를 가지고 놀 수 있기 때문에 호석이는 세상 모든 정보를 모으는 "정보 상인"이 되고 싶다. 정보 상인은 정보를 사고파는 사람을 의미한다.

    호석이는 아직 상인계의 새싹이기 때문에, 초기 투자를 통해서 여러 명의 "정보 고릴라"들로부터 정보를 모으려고 한다. 정보 고릴라란 여기저기서 정보를 수집하는 사람들을 의미한다. 일단 정보를 긁어모으기 위해서 호석이는 여러 정보 고릴라들에게 정보를 구매하려고 한다.

    암흑가의 연락망은 빼곡하기 때문에 누가 어떤 정보를 얻었는지에 대한 찌라시들이 수시로 퍼진다. 찌라시로 알 수 있는 것은, 어떤 이름을 가진 고릴라가 C1, C2, ..., Ck 만큼의 가치가 있는 정보 k 개를 얻었다는 점이다.

    호석이는 이를 바탕으로 임의의 시점에 특정 고릴라에게 정보를 몇 개 살 것인지를 정할 수 있다. 이때 가치 순으로 가장 비싼 정보들을 구매한다. 예를 들어 고릴라가 가진 정보가 10개이고, 호석이가 사고 싶은 정보 개수가 4개라면, 고릴라는 10개 중에서 가치 순으로 가장 비싼 4개를 팔 것이다. 한 번 거래한 정보는 호석이에게 더 이상 가치가 없기 때문에 고릴라도 그 정보를 파기한다.

    당신은 암흑가의 주먹이며 양대 산맥이 될 가능성이 있는 호석이를 주시하고 있다. 관찰하면서 얻은 정보는 총 Q 개이다. 각 정보는 다음의 2가지 중 하나이다.

    • 1 Name k C1,C2,...,Ck : 이름이 [Name]인 고릴라가 k 개의 정보를 얻었으며, 각 가치는 C1 부터 Ck 이다.
    • 2 Name b : 호석이가 이름이 [Name]인 고릴라에게 b 개의 정보를 구매한다. 이때 고릴라가 가진 정보들 중 가장 비싼 b 개를 구매하며, 고릴라가 가진 정보가 b개 이하이면 가진 모든 정보를 구매한다.

     견제를 위해서 호석이가 가진 정보들의 가치 총합, 즉 호석이가 정보들을 구매하는 데에 쓴 돈의 총합을 구하자.

     

    입력

    고릴라들이 정보를 얻는 사건과 호석이가 거래하는 정보가 시간순으로 주어진다. 첫 번째 줄에는 쿼리의 개수 Q 가 주어진다.

    이어서 Q 개의 줄에 걸쳐서 각 줄에 쿼리가 주어진다. 쿼리는 1이나 2로 시작한다. 1로 시작하는 경우에는 정보를 얻은 정보 고릴라의 이름과 k 가 주어지며 이어서 k 개의 정보 가치 C1,...,Ck가 자연수로 주어진다. 모든 Ci는 1 이상 100,000 이하이다. 2로 시작하는 경우에는 호석이가 거래하려는 정보 고릴라의 이름과 구매하려는 정보의 개수 b가 주어진다. 

     

    출력

    모든 쿼리가 종료되었을 때에 호석이가 얻게 되는 정보 가치의 총합을 출력하라.

     

    제한

    • 1 ≤ Q ≤ 100,000, Q 는 자연수
    • 모든 Name은 알파벳 소문자 혹은 대문자로 이루어져 있고 공백이 없으며 길이는 1 이상 15 이하이다.
    • 1 ≤ k ≤ 100,000, k 는 자연수
    • 1 ≤ C ≤ 100,000, C 는 자연수
    • 1 ≤ b ≤ 100,000, b 는 자연수
    • 모든 쿼리에 대한 k 의 합은 1,000,000 을 넘지 않는다. 

     

     

    풀이

    입력이 1인 경우 고릴라의 이름, 정보의 갯수, 가치가 들어온다.
    입력이 2인 경우 고릴라의 이름, 구입할 정보의 갯수가 들어온다.

     

    sellers = defaultdict(list)

    고릴라를 특정지을 수 있는 인자는 고릴라의 이름이기 때문에 dictionary 자료형을 이용하여
    key를 고릴라의 이름으로 value를 정보로 설정하면 된다.

        if data[0] == '1':
            for i in range(3, len(data)):
                heapq.heappush(sellers[data[1]],  -int(data[i]))

    정보가 정렬되어 있지 않고 여러번 나눠서 들어올 수 있기 때문에 pq를 사용해서 value를 저장한다.

     

    elif data[0] == '2':
            for i in range(int(data[2])):
                if len(sellers[data[1]]):
                    t = heapq.heappop(sellers[data[1]])

    2인 경우에 구매하는 정보의 수만큼 pop을 진행한다.

     

    시간초과가 발생하였는데 정보의 POP하는 과정에서 시간이 너무 많이 소모되는 것 같다.
    정보의 갯수보다 구매하는 갯수가 많은 경우에 구매하는 횟수만큼 POP을 진행하지만,
    실제 데이터는 갯수만큼 나가기 때문이다.

    실제 데이터 갯수는 2개인데 POP을 100번 진행하는 경우에 많은 시간이 낭비된다.

     

    count = int(data[2])
            if len(sellers[data[1]]) <= count:
                answer -= sum(sellers[data[1]])
                sellers[data[1]] = []
            else:
                for i in range(count):
                    answer -= heapq.heappop(sellers[data[1]])

    데이터의 갯수가 적은 경우네는 POP을 수행하지 않고 SUM을 이용해서 데이터의 갯수가 있는 만큼만
    N으로 계산하고 해당 key에 대한 value를 초기화했다.

     

    전체 코드

    from collections import defaultdict
    import heapq
    import sys
    
    N = int(sys.stdin.readline().rstrip())
    
    sellers = defaultdict(list)
    answer = 0
    for i in range(N):
        data = sys.stdin.readline().split()
    
        if data[0] == '1':
            for i in range(3, len(data)):
                heapq.heappush(sellers[data[1]],  -int(data[i]))
        else:
            count = int(data[2])
            if len(sellers[data[1]]) <= count:
                answer -= sum(sellers[data[1]])
                sellers[data[1]] = []
            else:
                for i in range(count):
                    answer -= heapq.heappop(sellers[data[1]])
    
    print(answer)

    sum을 이용해서 계산하니 문제없이 해결했다.

    elif data[0] == '2':
            for i in range(int(data[2])):
                if len(sellers[data[1]]):
                    t = heapq.heappop(sellers[data[1]])
                    answer += t
                else:
                    break

    sum이 아니라 break를 이용해서 데이터가 없는 경우에 멈추는 방식으로 해결해도 시간 내에 해결할 수 있었다.

    하지만 시간이 1.5배정도 차이나는 것을 보니 N과 NlogN의 시간 차이인 것 같다.

    'Algorithm Study > Python' 카테고리의 다른 글

    [백준] 5525번 IOIOI  (3) 2021.09.08
    [백준] 11000 강의실 배정  (0) 2021.08.30
    [백준] 20040번 사이클 게임  (0) 2021.08.24
    [백준] 17391번 무한부스터  (0) 2021.08.24
    [백준] 2468번 안전 영역  (0) 2021.08.24

    댓글

From BlackHair