https://www.acmicpc.net/problem/14287
14287번: 회사 문화 3
영선회사에는 매우 좋은 문화가 있는데, 바로 상사가 직속 부하를 칭찬하면 그 부하가 부하의 직속 부하를 연쇄적으로 칭찬하는 내리 칭찬이 있다. 즉, 상사가 한 직속 부하를 칭찬하면 그 부하
www.acmicpc.net
[ 문제풀이 ]
이 문제를 풀기 전에 다음 글을 먼저 읽고 오시는 것을 추천드립니다.
https://rudalsd.tistory.com/364
[ 자료구조 ] 비재귀 세그먼트 트리 (Segment Tree)
1. 비재귀 세그먼트 트리 (Segment Tree) 재귀 세그먼트 트리에서는 항상 루트노드부터 시작했었습니다. 하지만 비재귀 세그먼트 트리에서는 반대로 리프노드부터 시작합니다. 2. 비재귀 세그먼트
rudalsd.tistory.com
1. dfs를 통해 각 노드가 몇 번에서 시작해서 몇 번에서 끝나는지 오일러 경로 테크닉을 이용하여 s[ n ], e[ n ]에 저장합니다.
2. 세그먼트 트리를 이용하여 각 노드의 값을 업데이트 해주고, 구간합을 출력해줍니다.
[ 소스코드 ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | #include<iostream> #include<vector> using namespace std; int n, m; int segTree[200000]; int s[100001]; int e[100001]; int cnt = -1; vector<int> list[100001]; void dfs(int num) { s[num] = ++cnt; for (int& next : list[num]) { dfs(next); } e[num] = cnt; } void updateTree(int node, int w) { while (node != 0) { segTree[node] += w; node >>= 1; } } int getTree(int left, int right) { int ret = 0; while (left <= right) { if (left % 2 == 1) { ret += segTree[left]; left += 1; } if (right % 2 == 0) { ret += segTree[right]; right -= 1; } left >>= 1; right >>= 1; } return ret; } int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) { int parent; scanf("%d", &parent); if (parent != -1) { list[parent].push_back(i); } } dfs(1); for (int j = 0; j < m; j++) { int com, i; scanf("%d %d", &com, &i); if (com == 1) { int w; scanf("%d", &w); updateTree(s[i] + n, w); } else { printf("%d\n", getTree(n + s[i], n + e[i])); } } } | cs |
'백준' 카테고리의 다른 글
[ 백준 ] 16404번 - 주식회사 승범이네 (C++) (0) | 2023.05.12 |
---|---|
[ 백준 ] 14288번 - 회사 문화 4 (C++) (0) | 2023.05.11 |
[ 백준 ] 14268번 - 회사 문화 2 (C++) (0) | 2023.05.09 |
[ 백준 ] 14267번 - 회사 문화 1 (C++) (0) | 2023.05.08 |
[ 백준 ] 14419번 - Foehn Phenomena (C++) (0) | 2023.05.07 |