3 minute read

1. 덩치

  • 우리는 사람의 덩치를 키와 몸무게, 이 두 개의 값으로 표현하여 그 등수를 매겨보려고 한다.
  • 어떤 사람의 몸무게가 x kg이고 키가 y cm라면 이 사람의 덩치는 (x, y)로 표시된다.
  • 두 사람 A 와 B의 덩치가 각각 (x, y), (p, q)라고 할 때 x > p 그리고 y > q 이라면 우리는 A의 덩치가 B의 덩치보다 “더 크다”고 말한다.
    • 예를 들어 어떤 A, B 두 사람의 덩치가 각각 (56, 177), (45, 165) 라고 한다면 A의 덩치가 B보다 큰 셈이 된다.
    • 그런데 서로 다른 덩치끼리 크기를 정할 수 없는 경우도 있다.
    • 예를 들어 두 사람 C와 D의 덩치가 각각 (45, 181), (55, 173)이라면 몸무게는 D가 C보다 더 무겁고, 키는 C가 더 크므로, “덩치”로만 볼 때 C와 D는 누구도 상대방보다 더 크다고 말할 수 없다.
  • N명의 집단에서 각 사람의 덩치 등수는 자신보다 더 “큰 덩치”의 사람의 수로 정해진다.
  • 만일 자신보다 더 큰 덩치의 사람이 k명이라면 그 사람의 덩치 등수는 k+1이 된다.
  • 이렇게 등수를 결정하면 같은 덩치 등수를 가진 사람은 여러 명도 가능하다.
  • 아래는 5명으로 이루어진 집단에서 각 사람의 덩치와 그 등수가 표시된 표이다.
이름 (몸무게, 키) 덩치 등수
A (55, 185) 2
B (58, 183) 2
C (88, 186) 1
D (60, 175) 2
E (46, 155) 5
  • 위 표에서 C보다 더 큰 덩치의 사람이 없으므로 C는 1등이 된다.
  • 그리고 A, B, D 각각의 덩치보다 큰 사람은 C뿐이므로 이들은 모두 2등이 된다.
  • 그리고 E보다 큰 덩치는 A, B, C, D 이렇게 4명이므로 E의 덩치는 5등이 된다.
  • 위 경우에 3등과 4등은 존재하지 않는다.
  • 여러분은 학생 N명의 몸무게와 키가 담긴 입력을 읽어서 각 사람의 덩치 등수를 계산하여 출력해야 한다.

입력

  • 첫 줄에는 전체 사람의 수 N이 주어진다.
  • 그리고 이어지는 N개의 줄에는 각 사람의 몸무게와 키를 나타내는 양의 정수 x와 y가 하나의 공백을 두고 각각 나타난다.

출력

  • 여러분은 입력에 나열된 사람의 덩치 등수를 구해서 그 순서대로 첫 줄에 출력해야 한다.
  • 단, 각 덩치 등수는 공백문자로 분리되어야 한다.

풀이

import sys

N = int(sys.stdin.readline())
arr = []

for _ in range(0, N):
    weight, length = list(map(int, sys.stdin.readline().split()))
    arr.append((weight, length))

volume_arr = []

for i in range(0, N):
    tmp_arr = []
    for j in range(0, N):
        if i != j:
            if arr[i][0] < arr[j][0] and arr[i][1] < arr[j][1]:
                tmp_arr.append(arr[j])

    volume_arr.append(len(tmp_arr))
print(' '.join([str(x+1) for x in volume_arr]))

채점 결과

  • 정답

리뷰

  • 각 인원에 대해 자신보다 덩치가 큰 사람의 수 + 1만큼 출력해준다.

2. 나무 자르기

  • 상근이는 나무 M미터가 필요하다. 근처에 나무를 구입할 곳이 모두 망해버렸기 때문에, 정부에 벌목 허가를 요청했다. 정부는 상근이네 집 근처의 나무 한 줄에 대한 벌목 허가를 내주었고, 상근이는 새로 구입한 목재절단기를 이용해서 나무를 구할것이다.

  • 목재절단기는 다음과 같이 동작한다.
  • 먼저, 상근이는 절단기에 높이 H를 지정해야 한다.
  • 높이를 지정하면 톱날이 땅으로부터 H미터 위로 올라간다. 그 다음, 한 줄에 연속해있는 나무를 모두 절단해버린다.
  • 따라서, 높이가 H보다 큰 나무는 H 위의 부분이 잘릴 것이고, 낮은 나무는 잘리지 않을 것이다.
    • 예를 들어, 한 줄에 연속해있는 나무의 높이가 20, 15, 10, 17이라고 하자.
    • 상근이가 높이를 15로 지정했다면, 나무를 자른 뒤의 높이는 15, 15, 10, 15가 될 것이고, 상근이는 길이가 5인 나무와 2인 나무를 들고 집에 갈 것이다.
    • (총 7미터를 집에 들고 간다)
    • 절단기에 설정할 수 있는 높이는 양의 정수 또는 0이다.
  • 상근이는 환경에 매우 관심이 많기 때문에, 나무를 필요한 만큼만 집으로 가져가려고 한다.
  • 이때, 적어도 M미터의 나무를 집에 가져가기 위해서 절단기에 설정할 수 있는 높이의 최댓값을 구하는 프로그램을 작성하시오.

입력

  • 첫째 줄에 나무의 수 N과 상근이가 집으로 가져가려고 하는 나무의 길이 M이 주어진다. (1 ≤ N ≤ 1,000,000, 1 ≤ M ≤ 2,000,000,000)

  • 둘째 줄에는 나무의 높이가 주어진다.

    • 나무의 높이의 합은 항상 M보다 크거나 같기 때문에, 상근이는 집에 필요한 나무를 항상 가져갈 수 있다.
    • 높이는 1,000,000,000보다 작거나 같은 양의 정수 또는 0이다.

출력

  • 적어도 M미터의 나무를 집에 가져가기 위해서 절단기에 설정할 수 있는 높이의 최댓값을 출력한다.

풀이

import sys

N, M = list(map(int, sys.stdin.readline().split()))
trees = list(map(int, sys.stdin.readline().split()))

right = max(trees)
left = 0


def search(left, right, trees, M):
    mid = (right + left) // 2
    if left > right:
        return mid

    if sum([x - mid for x in trees if x - mid > 0]) > M:
        return search(mid + 1, right, trees, M)
    elif sum([x - mid for x in trees if x - mid > 0]) < M:
        return search(left, mid - 1, trees, M)
    else:
        return mid


print(search(left, right, trees, M))

채점 결과

  • 정답

리뷰

  • 이분탐색을 통해 풀어야 하는 문제였다.

  • x가 mid보다 큰 경우의 합(절단기로 잘라낸 나무의 길이의 합)과 M을 비교하여 이분탐색을 진행한다.