Open WonYong-Jang opened 6 years ago
public static long init(int node, int start, int end)
{
int mid = (start + end) / 2;
if(start == end) return tree[node] = data[start];
else return tree[node] = init(node*2, start, mid) + init(node*2+1, mid+1, end);
}
public static void update(int node, int start, int end, int target, long diff)
{
if(start > target || end < target) return;
tree[node]+= diff;
if(start == end) return;
int mid = (start + end) / 2;
update(node*2, start, mid, target, diff);
update(node*2+1, mid+1, end, target, diff);
}
public static long sum(int node, int start, int end, int i, int j)
{
int mid = (start + end) / 2;
if(i > end || j < start) return 0;
else if(i <= start && end <= j) return tree[node];
else return sum(node*2, start, mid, i, j) + sum(node*2+1, mid+1, end, i, j);
}
필요할 때에만 함으로써 하나의 자료뿐만 아니라 구간 내의 자료들 전부를 업데이트 하는 연산마저 O(logN)에 수행 가능
구간 업데이트 정보를 반영하기 위해 조상노드의 lazy가 자손노드에 필요한 상황이라면 반드시 조상노드를 거쳐야 자손노드에 도달 할수 있기 때문에 조상 노드를 지날 때 마다 아래쪽을 lazy를 전파 시키면 됨
이때 한번 아래쪽으로 전파시키고 나면 다음에 또 지나가면서 같은 lazy가 두번 전파되면 안되기 때문에 lazy값을 대표노드의 값으로 반영하고 0으로 만들어 줌
public static long sum(int node, int start, int end, int i, int j)
{
if(tree[node].lazy != 0 )
{
tree[node].num += (end - start + 1)*tree[node].lazy;
if(start != end)
{
tree[node*2].lazy += tree[node].lazy;
tree[node*2+1].lazy += tree[node].lazy;
}
tree[node].lazy = 0;
}
if(i > end || j < start) return 0;
else if(i <= start && end <= j)
{
return tree[node].num;
}
else
{
int mid = (start + end) / 2;
return sum(node*2, start, mid, i, j) + sum(node*2+1, mid+1, end, i, j);
}
}
public static void update(int node, int start, int end, int i, int j, long value)
{
if(tree[node].lazy != 0)
{
tree[node].num += (end - start + 1)*tree[node].lazy;
if(start != end)
{
tree[node*2].lazy += tree[node].lazy;
tree[node*2+1].lazy += tree[node].lazy;
}
tree[node].lazy =0;
}
if(i > end || j < start) return;
else if(i <= start && end <= j)
{
tree[node].num += ( end - start + 1)*value;
if(start != end)
{
tree[node*2].lazy += value;
tree[node*2+1].lazy += value;
}
return;
}
else
{
int mid = (start + end) / 2;
update(node*2, start, mid, i, j, value);
update(node*2+1, mid+1, end, i, j, value);
tree[node].num = tree[node*2].num + tree[node*2+1].num;
}
}
참고 링크 : https://bowbowbow.tistory.com/4
모든 쿼리 Q = (s, e)에 대해, ([s/√N], e) 순으로 오름차순 정렬
Segment Tree / Index Tree
백준 관련 문제 2042, 10868, 2357 ( 구간 합, 곱, 최대 최소 구할때 )
트리 시작점
리프 노드에 입력값을 모두 넣어야 하므로 루트 인덱스 1 부터 자식 노드로 내려오면서 N보다 커지는 인덱스가 시작 위치로 지정
값이 N일때 트리 구성하기 위한 전체 배열을 N*4 로 구성 !
N = 9 일 때 포화 이진트리 구성하기 위한 전체 배열은 31개가 나오므로
트리 구성
구간 값 구하기
구간 합 구하기
참고 문제