https://www.acmicpc.net/blog/view/26
세그먼트 트리 나중에 업데이트 해야지!
글이 업데이트 되었습니다. https://book.acmicpc.net/ds/segment-tree-lazy-propagation 배열 A가 있고, 여기서 다음과 같은 두 연산을 수행해야하는 문제가 있습니다. 10999번 문제: 구간 합 구하기 2 구간 l, r (l
www.acmicpc.net
https://steady-coding.tistory.com/129
[BOJ] 백준 6549번 : 히스토그램에서 가장 큰 직사각형 (JAVA)
문제 히스토그램은 직사각형 여러 개가 아래쪽으로 정렬되어 있는 도형이다. 각 직사각형은 같은 너비를 가지고 있지만, 높이는 서로 다를 수도 있다. 예를 들어, 왼쪽 그림은 높이가 2, 1, 4, 5, 1,
steady-coding.tistory.com
index tree는 기존의 세그트리와 다르게
최소(최대)값이 저장되어있지 않고, 최소(최대)값의 "위치"를 담고 있다.
여기서의 위치는 1~n번 값을 따로 저장해놓은 배열에서의 위치를 의미.
segment tree lazt propagation은
10999 구간합2 처럼 "값 업데이트가 여러 범위에 걸쳐 일어날 경우" 매번 해당 칸들을 전부 업데이트해주면
tle가 나오기 때문에, left <= lo && hi <= right 일때 그 밑의 노드들의 업데이트는 미루고
lazy 배열에 저장해두었다가 나중에 탐색할 일이 있을 때 방문하는 김에 lazy()로 갱신!
(lazy[i] != 0이면 lazy로 갱신할 값이 존재한다는 뜻)
파란 노드를 루트로 가지는 모든 노드들을 업데이트하지 않고,
파란 노드에서 좌우의 노드에게 lazy값을 추가해준 뒤 업데이트를 멈춘다!
static long init(int left, int right, int node){
if (left == right) return tree[node] = val[left];
int mid = (left + right) / 2;
return tree[node] = init(left, mid, node * 2) + init(mid + 1, right, node * 2 + 1);
}
제일 처음에 들어오는 값들은 init으로 정상적으로 받아준다
static void update(int lo, int hi, int node, int left, int right, long value){
lazy(lo, hi, node);
if (hi < left || right < lo) return;
if (left <= lo && hi <= right){
tree[node] += (hi - lo + 1) * value;
if (lo != hi){
lazy[node * 2] += value;
lazy[node * 2 + 1] += value;
}
return;
}
int mid = (lo + hi) / 2;
update(lo, mid, node * 2, left, right, value);
update(mid + 1, hi, node * 2 + 1, left, right, value);
tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
static void lazy(int lo, int hi, int node){
if (lazy[node] != 0){
tree[node] += lazy[node] * (hi - lo + 1);
if (lo != hi){
lazy[node * 2] += lazy[node];
lazy[node * 2 + 1] += lazy[node];
}
lazy[node] = 0;
}
}
업데이트가 일어나면 매 노드 방문시마다 항상 lazy에 값이 밀려있는지 확인
해당 노드가 루트인 경우 모두 갱신해야한다면
"올바르게" tree[node] 값 갱신 => value 값을 (hi - lo + 1)번 더해줘야함.
static long sum(int lo, int hi, int node, int left, int right){
lazy(lo, hi, node);
if (hi < left || right < lo) return 0;
if (left <= lo && hi <= right) return tree[node];
int mid = (lo + hi) / 2;
return sum(lo, mid, node * 2, left, right) + sum(mid + 1, hi, node * 2 + 1, left, right);
}
합을 구해줄때도 꼭 각 노드 방문시마다 lazy 체크
'PS > Algorithms' 카테고리의 다른 글
[Java] Millar-Rabin primality test (0) | 2022.05.19 |
---|---|
[Java] LCA (Lowest Common Ancestor) (0) | 2022.05.17 |
[Java] Segment Tree (0) | 2022.03.14 |
[Java] 2-Dimentional Fenwick Tree (0) | 2022.03.13 |
[Java] TSP (Traveling Salesperson Problem) - 모든 노드를 지나는 최소 길이 사이클 (0) | 2022.02.20 |