====== 회사 문화 3 ====== ===== 풀이 ===== * [[ps:problems:boj:14268|회사 문화 2]]에서 칭찬의 방향이 바뀐 문제이다. * [[ps:problems:boj:14268|회사 문화 2]]에서 했던 것처럼 매번 칭찬의 대상자들의 칭찬값을 구간 업데이트로 처리하려고 하면, 루트로 이어지는 경로상의 노드들을 모두 업데이트 해야 하므로 Heavy light decomposition 이 필요하다. * 하지만, 굳이 모든 노드의 값을 모두 구간 업데이트로 처리하지 않더라도, 직접 칭찬을 받은 당사자에 대해서만 값을 업데이트 해두면, 어떤 사람이 받은 칭찬의 합을 그 부하들이 받은 직접칭찬의 합으로 계산이 가능하다. 따라서 이 경우에는 [[ps:구간 쿼리#오일러 경로 테크닉]]으로 서브트리들을 인접 구간으로 모은 뒤, 포인트 업데이트 + 구간합 쿼리로 처리 가능하다 * 오일러 경로 테크닉을 적용하는 데에 O(N)이 걸리고, 펜윅트리로 포인트 업데이트와 구간합 쿼리를 처리하는 데에는 각각 O(logN)이 든다. 따라서 전처리 시간과 M개의 쿼리를 처리하는 시간을 합치면 O(N+MlogN) ===== 코드 ===== """Solution code for "BOJ 14287. 회사 문화 3". - Problem link: https://www.acmicpc.net/problem/14287 - Solution link: http://www.teferi.net/ps/problems/boj/14287 """ import sys from teflib import fenwicktree from teflib import tgraph def euler_tour_technique(tree, root): subtree_ranges = [[None, None] for _ in tree] order = 0 for node in tgraph.dfs(tree, root, yields_on_leave=True): if subtree_ranges[node][0] is None: subtree_ranges[node][0] = order order += 1 else: subtree_ranges[node][1] = order return subtree_ranges def main(): n, m = [int(x) for x in sys.stdin.readline().split()] tree = [[] for _ in range(n)] bosses = [int(x) for x in sys.stdin.readline().split()] for employee, boss in enumerate(bosses): if boss != -1: tree[boss - 1].append(employee) subtree_ranges = euler_tour_technique(tree, 0) fenwick = fenwicktree.FenwickTree(n + 1) for _ in range(m): query = [int(x) for x in sys.stdin.readline().split()] if query[0] == 1: _, i, w = query fenwick.update(subtree_ranges[i - 1][0], w) else: i = query[1] print(fenwick.query(*subtree_ranges[i - 1])) if __name__ == '__main__': main() * Dependency * [[:ps:teflib:fenwicktree#FenwickTree|teflib.fenwicktree.FenwickTree]] * [[:ps:teflib:tgraph#dfs|teflib.tgraph.dfs]] {{tag>BOJ ps:problems:boj:플래티넘_4}}