첫째 줄에 노드 개수 N이 주어진다. (1 ≤ N ≤ 262,143, N은 2^k-1 꼴의 자연수) 둘째 줄에 노드의 가중치 Wi가 노드 번호 순서대로 주어진다. (-10^9 ≤ Wi ≤ 10^9) 루트 노드의 번호는 1이고, i번 노드의 좌우 자식 노드의 번호는 각각 2×i, 2×i+1이다.
출력
욱제가 얻을 수 있는 가중치의 최대 합을 출력한다.
입력 예시
15
-2 8 -3 -9 0 -6 3 4 -1 10 -1 7 -100 7 -1
출력 예시
24
풀이
잘 생각해 보면, 직사각형의 y축은 depth의 차가 된다. 즉 depth 구간 내에 속하는 모든 가중치에 대해, 가중치 연속 부분합의 최대를 구하는 문제로 볼 수 있겠다. 이는 O(N)의 시간복잡도가 소요된다. (카데인 알고리즘. DP 문제의 일종으로 볼 수 있으며 O(N)시간 내에 모두 풀이할 수 있겠다)
또한 아주 감사하게도 포화 이진트리의 형태이므로, 이 트리의 depth는 logN의 범위를 가진다. 즉 O((logN)^2)의 탐색을 통하여 모든 구간 내에서의 연속 부분합을 전부 탐색해 볼 수 있고, 그 중 최댓값이 문제에서 요구하는 정답이 된다. (이거 왜 A번이라고 생각하신거죠..)
최종적으로 O(N(logN)^2)의 시간복잡도 내에 문제를 풀이할 수 있겠다.
p.s. 문제에서 주어지는 가중치 리스트는 y축 - x축 순서로 배열되어 있으므로, 이를 적당히 가공해줄 필요가 있다.
p.s.2. 어떻게 DFS로 푸는지는 아직도 감이 잘 오지 않는다... 출제자의 의도가 궁금하다
풀이 코드
N = int(input())
num_list = list(map(int, input().split()))
ans = -float('inf')
depth_list = [0]*N
def div_and_con(start, end, depth) :
mid = (start + end) // 2
depth_list[mid] = depth
if start == end :
return
div_and_con(start, mid-1, depth+1)
div_and_con(mid+1, end, depth+1)
def maximum_subquery(mindepth, maxdepth) :
global ans
result = None
for i in range(N) :
if not mindepth <= depth_list[i] <= maxdepth :
continue
if result is None :
result = num_list[i]
else :
result = max(result + num_list[i], num_list[i])
ans = max(ans, result)
div_and_con(0, N-1, 0)
maxdepth = max(depth_list)
for i in range(maxdepth) :
for j in range(i+1, maxdepth+1)