https://www.acmicpc.net/problem/2820
2820번: 자동차 공장
상근이는 자동차를 매우 좋아한다. 자동차 공장에 취직한 상근이는 계속된 승진 끝에 드디어 사장이 되었다. 공장에는 총 N명의 직원이 있다. 상근이를 제외한 모든 직원은 한 명의 상사가 있다.
www.acmicpc.net
[ 문제풀이 ]
이 문제를 풀기 전에 다음 글을 먼저 읽고 오시는 것을 추천드립니다.
https://rudalsd.tistory.com/256
[ 자료구조 ] 느리게 갱신되는 세그먼트 트리 (Lazy Propagation)
https://rudalsd.tistory.com/51 [ 자료구조 ] 세그먼트 트리 (Segment Tree) 1. 세그먼트 트리 (Segment Tree) 먼저, 세그먼트 트리가 무엇인지 알아봅시다! 세그먼트 트리는 구간 합을 저장하기 위한 트리입니다.
rudalsd.tistory.com
1. 초기 월급을 arr배열에 저장하고, 그래프를 list에 저장합니다.
2. dfs를 통해 각 노드가 몇 번에서 시작해서 몇 번에서 끝나는지 오일러 경로 테크닉을 이용하여 st[ n ], en[ n ]에 저장하고, arr2[ st[ n ] ] = arr[ n ] 을 통해 초기화해 줍니다.
3. 초기 segmentTree를 만들 때 arr2를 기준으로 만듭니다.
4. 월급이 오르거나 내리면 느리게 갱신되는 세그먼트 트리를 이용하여 st[ i ] + 1부터 en[ i ]까지 월급을 더해줍니다.
5. segTree에서 해당 노드를 출력해 줍니다.
[ 소스코드 ]
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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | #include<iostream> #include<vector> using namespace std; int N, M; unsigned int segTree[1050000]; unsigned int lazy[1050000]; vector<int> list[500001]; int st[500001]; int en[500001]; int arr[500001]; int arr2[500001]; int cnt; void dfs(int num) { st[num] = ++cnt; arr2[cnt] = arr[num]; for (int& next : list[num]) { dfs(next); } en[num] = cnt; } void makeTree(int node, int s, int e) { if (s == e) { segTree[node] = arr2[s]; return; } int m = (s + e) / 2; makeTree(node * 2, s, m); makeTree(node * 2 + 1, m + 1, e); } void updateLazy(int node, int s, int e) { if (lazy[node] != 0) { segTree[node] += lazy[node]; if (s != e) { lazy[node * 2] += lazy[node]; lazy[node * 2 + 1] += lazy[node]; } lazy[node] = 0; } } void updateTree(int node, int s, int e, int sidx, int eidx, unsigned int diff) { updateLazy(node, s, e); if (e < sidx || s > eidx) return; if (sidx <= s && e <= eidx) { if (s == e) { segTree[node] += diff; } else { lazy[node * 2] += diff; lazy[node * 2 + 1] += diff; } return; } int m = (s + e) / 2; updateTree(node * 2, s, m, sidx, eidx, diff); updateTree(node * 2 + 1, m + 1, e, sidx, eidx, diff); } void getTree(int node, int s, int e, int idx) { updateLazy(node, s, e); if (idx < s || idx > e) return; if (s == e) { cout << segTree[node] << '\n'; return; } int m = (s + e) / 2; getTree(node * 2, s, m, idx); getTree(node * 2 + 1, m + 1, e, idx); } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); cin >> N >> M; for (int i = 1; i <= N; i++) { cin >> arr[i]; if (i != 1) { int p; cin >> p; list[p].push_back(i); } } dfs(1); makeTree(1, 1, N); for (int i = 0; i < M; i++) { char com; int a; cin >> com >> a; if (com == 'p') { unsigned int x; cin >> x; updateTree(1, 1, N, st[a] + 1, en[a], x); } else { getTree(1, 1, N, st[a]); } } } | cs |
'백준' 카테고리의 다른 글
[ 백준 ] 2310번 - 어드벤처 게임 (C++) (0) | 2023.05.15 |
---|---|
[ 백준 ] 1800번 - 인터넷 설치 (C++) (0) | 2023.05.14 |
[ 백준 ] 16404번 - 주식회사 승범이네 (C++) (0) | 2023.05.12 |
[ 백준 ] 14288번 - 회사 문화 4 (C++) (0) | 2023.05.11 |
[ 백준 ] 14287번 - 회사 문화 3 (C++) (0) | 2023.05.10 |