BOJ 14057 Towers

BOJ 14057 Towers

문제 링크:

문제 내용

높이가 모두 다른 NN채의 빌딩들이 좌우로 일렬로 서 있고 그 사이 어느 한 곳에 탑을 지으려고 합니다. 두 빌딩의 사이, 맨 왼쪽 빌딩보다 왼쪽, 맨 오른쪽 빌딩보다 오른쪽에 짓는 것 모두 가능하고, 탑의 높이도 모든 빌딩의 높이와 다릅니다.

ii번째 빌딩이 탑보다 왼쪽에 있고, 그 높이가 탑보다 낮으며, ii번째 빌딩과 탑 사이에 ii번째 빌딩보다 높은 빌딩이 없으면, ii번째 빌딩이 “탑에서 잘 보인다"고 말합니다. 지으려는 탑의 높이가 주어졌을 때, “탑에서 잘 보이는” 빌딩의 최대 개수를 구하는 쿼리를 KK번 수행하세요.

입력

첫째 줄에는 빌딩의 개수 NN과 쿼리의 개수 KK가 주어집니다. (1N106, 1K105)(1 \le N \le 10^6,\ 1 \le K \le 10^5)

둘째 줄에는 11 이상 10910^9 이하의 정수 NN개가 주어지며, 빌딩들의 높이를 나타냅니다.

셋째 줄에는 11 이상 10910^9 이하의 정수 KK개가 주어지며, 각 쿼리에서 지으려는 탑의 높이를 나타냅니다.

출력

입력과 같은 순서로 각 쿼리의 답을 한 줄에 공백으로 구분해서 출력합니다.

문제 풀이

스포일러

쿼리가 단 한 번이었다면, 모든 빌딩들을 왼쪽부터 보면서 단조 스택을 관리해 O(N)O(N)에 풀 수 있었을 것입니다. 하지만 쿼리가 KK번이기 때문에 이 스택을 여러 번의 쿼리 동안 재활용할 방법이 필요합니다.

한 가지 방법은 스택의 변화 과정을 트리로 저장하는 것입니다. 처음에 스택이 비어 있는 상태를 루트 노드로 정의하고, push를 하면 지금 보고 있는 빌딩의 높이를 key로 가진 새로운 자식을 만들면서 내려가고, pop을 하면 부모로 올라옵니다.

이렇게 트리를 만들고 나면, 탑의 높이가 tt일 때의 답은 tt보다 작은 key를 가진 노드들의 height 중 최댓값과 같습니다. 여기서 노드의 height란 leaf이면 11, 아니면 자식 중 가장 큰 height에 11을 더한 값으로 정의합니다. 빌딩들의 높이와 혼동하지 않도록 주의하세요.

DFS를 돌아 height 값들을 구한 다음, key를 기준으로 오름차순 정렬하고 prefix max를 취해 놓으면 탑의 높이가 주어질 때마다 이분 탐색으로 답을 구할 수 있습니다. 따라서 전체 문제를 O((N+K)logN)O((N+K) \log N) 시간에 해결할 수 있습니다.

Last updated on