
백준 나무자르기 문제이다. 해당 문제는 이진 탐색을 통해 풀어야 시간초과가 나지 않는다.
import sys
input = sys.stdin.readline
# n: 나무의 수, m: 필요한 나무 길이
n, m = map(int, input().split())
tree = list(map(int, input().split()))
# 이분 탐색의 탐색 범위: 최소 1부터 가장 큰 나무의 높이까지
start, end = 1, max(tree)
# 적절한 절단 높이를 찾기 위한 이분 탐색
while start <= end:
mid = (start + end) // 2 # 현재 설정할 절단기 높이 (중간값)
total = 0 # 잘린 나무 총 길이 계산
for i in tree:
if i >= mid:
total += i - mid # mid보다 큰 나무만 잘림
# 필요한 나무 길이 m보다 많이 잘렸으면 절단 높이를 더 높여도 됨
if total >= m:
start = mid + 1
# 너무 적게 잘렸으면 절단 높이를 낮춰야 함
else:
end = mid - 1
# 최종적으로 end는 나무를 m만큼 가져갈 수 있는 가장 높은 절단기 높이
print(end)
아이디어
알고리즘
시간복잡도

import sys
input = sys.stdin.readline
n = int(input())
stack = [] # 타워 인덱스 저장
towers = list(map(int, input().split())) # 타워의 높이와 순서
result = [0] * n # 결과를 저장할 리스트 (초기값은 전부 0)
for i in range(n):
# 현재 타워보다 낮은 타워는 레이저를 받을 수 없으므로 제거
while stack and towers[stack[-1]] < towers[i]:
stack.pop()
if stack:
# 스택이 비어 있지 않으면 → 현재 타워의 레이저가 닿는 타워가 있음
# stack[-1]은 레이저를 수신하는 가장 가까운 왼쪽 타워의 인덱스
result[i] = stack[-1] + 1 # +1은 문제에서 인덱스가 1부터 시작하기 때문
else:
# 스택이 비어 있으면 → 왼쪽에 자신보다 높은 타워가 없음 → 0 (기본값 유지)
pass
# 현재 타워의 인덱스를 스택에 추가
# 이후 들어올 타워들의 레이저 수신 여부를 판단할 기준이 됨
stack.append(i)
# 결과 출력 (리스트를 언팩하여 공백 구분으로 출력)
print(*result)
아이디어
알고리즘
시간복잡도
나무 쓱싹쓱싹