Top 37 구간 트리 The 27 Latest Answer

You are looking for information, articles, knowledge about the topic nail salons open on sunday near me 구간 트리 on Google, you do not find the information you need! Here are the best content compiled and compiled by the https://chewathai27.com/to team, along with other related topics such as: 구간 트리 세그먼트 트리, 백준 2357, 세그먼트 트리 파이썬, 백준 최대값, 펜윅 트리, Segment tree js, 히스토그램에서 가장 큰 직사각형


1시간 l 뷔 (BTS) – Christmas Tree (그 해 우리는 OST) / 가사 Lyrics 방탄소년단 V
1시간 l 뷔 (BTS) – Christmas Tree (그 해 우리는 OST) / 가사 Lyrics 방탄소년단 V


[자료구조] 세그먼트 트리(구간트리, Segment Tree)로 구간 내 최소값 찾기 :: 코딩 공부 일지

  • Article author: cocoon1787.tistory.com
  • Reviews from users: 48692 ⭐ Ratings
  • Top rated: 4.5 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about [자료구조] 세그먼트 트리(구간트리, Segment Tree)로 구간 내 최소값 찾기 :: 코딩 공부 일지 세그먼트 트리(Segment Tree)란? 알고리즘 문제를 풀다 보면 정렬되어 있지 않은 구간 내의 합이나 최솟값들을 빠르게 찾아야 하는 경우가 많습니다. …
  • Most searched keywords: Whether you are looking for [자료구조] 세그먼트 트리(구간트리, Segment Tree)로 구간 내 최소값 찾기 :: 코딩 공부 일지 세그먼트 트리(Segment Tree)란? 알고리즘 문제를 풀다 보면 정렬되어 있지 않은 구간 내의 합이나 최솟값들을 빠르게 찾아야 하는 경우가 많습니다. 세그먼트 트리(Segment Tree)란? 알고리즘 문제를 풀다 보면 정렬되어 있지 않은 구간 내의 합이나 최솟값들을 빠르게 찾아야 하는 경우가 많습니다. 질문이 1개일 경우 간단하게 for문을 통해서 O(N)의 시간 복..개발 블로그
  • Table of Contents:
[자료구조] 세그먼트 트리(구간트리 Segment Tree)로 구간 내 최소값 찾기

세그먼트 트리(Segment Tree)란

티스토리툴바

[자료구조] 세그먼트 트리(구간트리, Segment Tree)로 구간 내 최소값 찾기 :: 코딩 공부 일지
[자료구조] 세그먼트 트리(구간트리, Segment Tree)로 구간 내 최소값 찾기 :: 코딩 공부 일지

Read More

구간 트리(Segment Tree)

  • Article author: javachoi.tistory.com
  • Reviews from users: 28048 ⭐ Ratings
  • Top rated: 4.6 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 구간 트리(Segment Tree) 구간 트리의 정체는 이진 트리입니다. 구간 트리 라는 이름은 그저 특정 용도로 사용되는 이진 트리의 한 형태를 나타낼 뿐입니다. 대게 구간 트리는 … …
  • Most searched keywords: Whether you are looking for 구간 트리(Segment Tree) 구간 트리의 정체는 이진 트리입니다. 구간 트리 라는 이름은 그저 특정 용도로 사용되는 이진 트리의 한 형태를 나타낼 뿐입니다. 대게 구간 트리는 … 구간 트리란? 구간 트리의 정체는 이진 트리입니다. 구간 트리 라는 이름은 그저 특정 용도로 사용되는 이진 트리의 한 형태를 나타낼 뿐입니다. 대게 구간 트리는 일차원 배열 상의 특정 구간에 대한 요청에 빠르..
  • Table of Contents:

Hello Freakin world!

구간 트리(Segment Tree) 본문

구간 트리란

구간 트리의 초기화

구간 트리의 질의 처리

구간 트리의 수정

구간 트리(Segment Tree)
구간 트리(Segment Tree)

Read More

세그먼트 트리 (구간 트리, Segment Tree) — Slowly but Surely

  • Article author: withseungryu.tistory.com
  • Reviews from users: 8505 ⭐ Ratings
  • Top rated: 4.6 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 세그먼트 트리 (구간 트리, Segment Tree) — Slowly but Surely ☞ 이렇게 이론적으로만 설명했지만, 코드 구현에 많은 어려움이 있을 수 있습니다. 그래서 세그먼트 트리 문제의 한 유형인 구간 최소 쿼리(range … …
  • Most searched keywords: Whether you are looking for 세그먼트 트리 (구간 트리, Segment Tree) — Slowly but Surely ☞ 이렇게 이론적으로만 설명했지만, 코드 구현에 많은 어려움이 있을 수 있습니다. 그래서 세그먼트 트리 문제의 한 유형인 구간 최소 쿼리(range … ☞ 세그먼트 트리란 이름 그대로 저장된 자료를 적절히 구간별로 전처리해 그들에 대한 질의들을 빠르게 대답할 수 있도록 해주는 트리입니다. 예를 들어 A={1,2,3,4,5}에서 [2,4] 구간의 최소치를 알고 싶다면..
  • Table of Contents:

블로그 메뉴

공지사항

인기 글

태그

최근 댓글

최근 글

티스토리

티스토리툴바

세그먼트 트리 (구간 트리, Segment Tree) — Slowly but Surely
세그먼트 트리 (구간 트리, Segment Tree) — Slowly but Surely

Read More

세그먼트 트리(Segment Tree)

  • Article author: coding-nyan.tistory.com
  • Reviews from users: 4362 ⭐ Ratings
  • Top rated: 3.0 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 세그먼트 트리(Segment Tree) 세그먼트 트리에 대한 글은 이미 많습니다. 심지어 다들 구체적으로 설명해주고 계십니다. 그런데 세그먼트 트리를 단지 구간합 트리라고 알고 계시는 … …
  • Most searched keywords: Whether you are looking for 세그먼트 트리(Segment Tree) 세그먼트 트리에 대한 글은 이미 많습니다. 심지어 다들 구체적으로 설명해주고 계십니다. 그런데 세그먼트 트리를 단지 구간합 트리라고 알고 계시는 … 세그먼트 트리에 대한 글은 이미 많습니다. 심지어 다들 구체적으로 설명해주고 계십니다. 그런데 세그먼트 트리를 단지 구간합 트리라고 알고 계시는 분들이 생각보다 많이 계신 이유로 오해를 정정하고자 포스팅..
  • Table of Contents:

세그먼트 트리(Segment Tree)

알고리즘이론 카테고리와 연관된 콘텐츠

0개의 댓글

티스토리툴바

세그먼트 트리(Segment Tree)
세그먼트 트리(Segment Tree)

Read More

[트리] Tree 6: Segment Tree구간 트리 , RMQ, 펜윅 트리(이진 인덱스 트리)

  • Article author: nsgg.tistory.com
  • Reviews from users: 31112 ⭐ Ratings
  • Top rated: 4.3 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about [트리] Tree 6: Segment Tree구간 트리 , RMQ, 펜윅 트리(이진 인덱스 트리) 1. 구간 트리(segment Tree). 구간 트리는 저장된 자료들을 적절히 전처리해 그들에 대한 질의들을 빠르게 대답할 수 있도록한다. (일차원 배열의 특정 … …
  • Most searched keywords: Whether you are looking for [트리] Tree 6: Segment Tree구간 트리 , RMQ, 펜윅 트리(이진 인덱스 트리) 1. 구간 트리(segment Tree). 구간 트리는 저장된 자료들을 적절히 전처리해 그들에 대한 질의들을 빠르게 대답할 수 있도록한다. (일차원 배열의 특정 … (일반적인 구간트리와는 다른 자료구조, 책에서는 알고리즘 문제를 풀기위한 자료구조를 설명한다.) (일반적인 구간트리는 1차원 좌표상의 구간들을 지정하고 특정 위치를 포함하는 구간들을 찾는 자료구조임.) 1…
  • Table of Contents:

1 구간 트리(segment Tree)

2 구간 최소 쿼리 (Range minimum query RMQ)

3 펜윅 트리(Fenwick Tree)(binary indexed tree)

펜윅트리의 구현

[트리] Tree 6: Segment Tree구간 트리 , RMQ, 펜윅 트리(이진 인덱스 트리)
[트리] Tree 6: Segment Tree구간 트리 , RMQ, 펜윅 트리(이진 인덱스 트리)

Read More

구간 트리(Segment tree) – 홍시홍의 프로그래밍

  • Article author: hsho.tistory.com
  • Reviews from users: 36213 ⭐ Ratings
  • Top rated: 4.9 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 구간 트리(Segment tree) – 홍시홍의 프로그래밍 구간 트리란. 구간의 합을 구하기 위한 트리. 시간 복잡도. O(logn). 트리 만들기. 구간 별 합을 저장할 수 있도록 한다. 트리는 완전 이진 트리로 … …
  • Most searched keywords: Whether you are looking for 구간 트리(Segment tree) – 홍시홍의 프로그래밍 구간 트리란. 구간의 합을 구하기 위한 트리. 시간 복잡도. O(logn). 트리 만들기. 구간 별 합을 저장할 수 있도록 한다. 트리는 완전 이진 트리로 … 구간 트리란 구간의 합을 구하기 위한 트리 시간 복잡도 O(logn) 트리 만들기 구간 별 합을 저장할 수 있도록 한다. 트리는 완전 이진 트리로 구성되어 있다 자식은 왼쪽 자식은 *2, 오른쪽 자식은 *2+1이다 위 점..
  • Table of Contents:

홍시홍의 프로그래밍

구간 트리(Segment tree) 본문

구간 트리(Segment tree) - 홍시홍의 프로그래밍
구간 트리(Segment tree) – 홍시홍의 프로그래밍

Read More

글 읽기 – 세그먼트(구간)트리 구현에 대해 질문 드립니다.

  • Article author: www.acmicpc.net
  • Reviews from users: 20139 ⭐ Ratings
  • Top rated: 3.6 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 글 읽기 – 세그먼트(구간)트리 구현에 대해 질문 드립니다. 세그먼트(구간)트리 구현에 대해 질문 드립니다. … 자세히 말하자면 세그먼트 트리를 연결리스트로 만드는 것까지는 성공했지만, 범위 탐색 과정을 어떻게 구현 … …
  • Most searched keywords: Whether you are looking for 글 읽기 – 세그먼트(구간)트리 구현에 대해 질문 드립니다. 세그먼트(구간)트리 구현에 대해 질문 드립니다. … 자세히 말하자면 세그먼트 트리를 연결리스트로 만드는 것까지는 성공했지만, 범위 탐색 과정을 어떻게 구현 … ACM-ICPC, ICPC, 프로그래밍, 온라인 저지, 정보올림피아드, 코딩, 알고리즘, 대회, 올림피아드, 자료구조
  • Table of Contents:

Baekjoon Online Judge

채점 현황

문제

유저 대회 고등학교 대회

출처

대학교 대회

도움말

글 읽기 - 세그먼트(구간)트리 구현에 대해 질문 드립니다.
글 읽기 – 세그먼트(구간)트리 구현에 대해 질문 드립니다.

Read More

구간트리(세그먼트트리;Segment tree) :: 잡블로그

  • Article author: wondy1128.tistory.com
  • Reviews from users: 46966 ⭐ Ratings
  • Top rated: 3.5 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 구간트리(세그먼트트리;Segment tree) :: 잡블로그 하지만 세그트리는 이러한 연산을 O(1) 만에 해결할 수 있다. 이러한 이유는 각 트리의 노드에 구간정보를 저장하고 있기 때문이다. 또한, 특정 구간을 … …
  • Most searched keywords: Whether you are looking for 구간트리(세그먼트트리;Segment tree) :: 잡블로그 하지만 세그트리는 이러한 연산을 O(1) 만에 해결할 수 있다. 이러한 이유는 각 트리의 노드에 구간정보를 저장하고 있기 때문이다. 또한, 특정 구간을 … 세그먼트 트리에 대해 정리. 1) 세그트리 구성에 필요한 크기 2) 세그트리 노드정보 3) 세그트리 초기화 4) 세그트리의 정보얻기 5) 세그트리 노드정보 업데이트 이진트리로 구성된 트리로 먼저, int형 데이터가 N..원도블로그입니다
  • Table of Contents:
구간트리(세그먼트트리;Segment tree) :: 잡블로그
구간트리(세그먼트트리;Segment tree) :: 잡블로그

Read More


See more articles in the same category here: https://chewathai27.com/to/blog.

[자료구조] 세그먼트 트리(구간트리, Segment Tree)로 구간 내 최소값 찾기

반응형

세그먼트 트리(Segment Tree)란?

알고리즘 문제를 풀다 보면 정렬되어 있지 않은 구간 내의 합이나 최솟값들을 빠르게 찾아야 하는 경우가 많습니다. 질문이 1개일 경우 간단하게 for문을 통해서 O(N)의 시간 복잡도로 최솟값이나 합을 구하는 것은 쉽습니다. 그러나 만약 질문의 수가 수 만개 혹은 수 십만 개라면? 실행시간 초과가 발생할 경우가 큽니다.

그러한 문제점을 해결하기 위해 세그먼트 트리가 사용되며 “배열의 구간정보를 담고 있는 트리”입니다. 세그먼트 트리를 이용할 경우 기존의 for문이 O(N)의 시간 복잡도보다 빠른 O(logN)의 시간 복잡도로 답을 빠르게 찾을 수 있게 됩니다.

예를 들어보겠습니다.

먼저 입력으로 받을 배열을 input[],

세그먼트 트리로 저장할 배열을 seg[]라고 할 때,

input = {7, 3, 2, 6, 5, 8, 1, 4}라고 합시다.

INDEX 0 1 2 3 4 5 6 7 input[ ] 7 3 2 6 5 8 1 4

입력된 배열로 segment tree를 만들어보면 다음과 같습니다.

먼저 트리의 맨 하단에는 input배열의 원소들이 있습니다.

그리고 최종적으로 만들어지는 세그먼트 트리는 다음과 같습니다.

각각의 세그먼트 트리들은 자식 노드들의 최솟값을 담고 있으며, 세그먼트 트리의 최상단인 seg[1]은 전 구간에서 최솟값인 “1”을 담고 있습니다.

이런 식으로 세그먼트 트리를 만드는 함수를 이제부터 init() 함수라고 하겠습니다.

int init(int node, int s, int e) { if (s == e) return seg[node] = input[s]; // start 와 end 의 위치가 일치하면 input[start] 값을 넣어준다. int mid = (s + e) / 2; return seg[node] = min(init(2 * node, s, mid), init(2 * node + 1, mid + 1, e)); // 다른 노드들의 정보를 }

init함수에서 파라미터로 받는 node는 부모의 노드, s는 구간의 시작, e는 구간의 끝을 의미합니다. 그리고 부모 노드를 node라고 할 때 왼쪽의 자식 노드의 번호는 2 * node, 그리고 오른쪽 자식의 노드 번호는 2 * node + 1이 됩니다.

return문을 살펴보면 seg[node] 즉, 현재의 노드 값은 왼쪽의 자식 노드의 값과 오른쪽의 자식 노드의 값 중에서 min값을 가져오게 됩니다. 그리고 init함수가 재귀적으로 내려갈 때, 맨 아래에서 s==e가 되는 순간 seg[node]의 값은 input[s]의 값으로 저장됩니다.

실제로 위의 함수를 이용해서 세그먼트 트리가 잘 구해졌는지 확인해보겠습니다.

<실행 코드>

#include #include #include using namespace std; #define INF 1000000000 // 10억 int input[8]; int seg[16]; int init(int node, int s, int e) { if (s == e) return seg[node] = input[s]; // start 와 end 의 위치가 일치하면 input[start] 값을 넣어준다. int mid = (s + e) / 2; return seg[node] = min(init(2 * node, s, mid), init(2 * node + 1, mid + 1, e)); // 다른 노드들의 정보를 } int main() { for (int i = 0; i < 8; i++) { cin >> input[i]; } init(1, 0, 7); // 세그먼트 트리 만들기 for (int i = 1; i < 16; i++) { cout << "seg[" << i << "] : " << seg[i] << endl; } } <실행 결과>

네 원하는 값들이 잘 구해졌습니다!

이런 식으로 세그먼트 트리를 생성하였다면 이제 구간정보가 주어졌을 때 해당 구간 내에 최솟값을 찾는 함수가 필요합니다.

이제부터 그 함수를 query() 함수라고 하겠습니다.

int query(int node, int s, int e, int l, int r) { if (e < l || r < s) return INF; // 찾아야하는 구간과 노드구간이 겹치지 않을 때 if (l <= s && e <= r) return seg[node]; // 찾아야하는 구간내에 노드구간이 포함될 때 int mid = (s + e) / 2; // 찾아야하는 구간이 노드구간에 포함되거나, 부분적으로 겹치는 경우 return min(query(2 * node, s, mid, l, r), query(2 * node + 1, mid + 1, e, l, r)); } query함수에서 파라미터로 받는 node, s, e는 init함수와 동일하고 l과 r은 "left", "right"의 앞글자로 찾을 구간을 의미합니다. 1. 찾아야 하는 구간과 노드 구간이 겹치지 않을 때 if (e < l || r < s) return INF; 찾지 않아도 되는 구간입니다. min함수에서 자동적으로 걸러지도록 INF를 리턴해줍니다. 2. 찾아야 하는 구간 내에 노드 구간이 포함될 때 if (l <= s && e <= r) return seg[node]; 더 이상 재귀적으로 들어가지 않아도 됩니다. 해당하는 노드의 segment 값을 리턴해줍니다. 3. 찾아야 하는 구간이 노드 구간에 포함되거나, 부분적으로 겹치는 경우 return min(query(2 * node, s, mid, l, r), query(2 * node + 1, mid + 1, e, l, r)); 위의 1번 경우나 2번 경우가 나올 때까지 재귀적으로 계속해서 들어가 줍니다. INDEX 0 1 2 3 4 5 6 7 input[ ] 7 3 2 6 5 8 1 4 이제 찾을 구간정보를 받으면 해당 구간 내의 최솟값을 정말 반환하는지 확인해보겠습니다. 구간정보를 2~6으로 주어진다고 생각해봅시다. 일단 위의 input배열에서 INDEX가 2~6일 때 input값의 최소는 "1"임을 쉽게 알 수 있습니다. 여기서 세그먼트 트리를 활용한다면 다음과 같은 그림으로 구하게 될 것입니다. 쿼리 함수를 통해 재귀적으로 들어가 보겠습니다. 먼저 1번 세그먼트(seg[1])에서 출발을 하게 됩니다. 1번 세그먼트는 (0~7)의 구간정보를 담고 있고 찾으려는 구간정보가 여기에 포함되므로 양쪽의 자식 노드로 recursion 합니다. 이제 세그먼트 2번과 3번의 경우 둘 다 찾으려는 구간정보와 포함하고 있는 구간정보가 겹치므로 다시 recursion 합니다. 이제 세그먼트 4,5,6,7번을 살펴봅시다. 세그먼트 4번의 경우 찾아야 하는 구간과 노드 구간이 겹치지 않으므로 자동적으로 걸러지도록 INF를 리턴. (return INF) 세그먼트 5, 6번의 경우 찾아야 하는 구간 내에 노드 구간이 포함되므로 해당 seg값 리턴. (return seg[5], seg[6]) 세그먼트 7번의 경우 찾아야 하는 구간과 노드 구간이 겹치므로 다시 recursion 해서 찾아야 하는 구간 내에 노드 구간이 포함되는 seg값을 리턴합니다. (return seg[14]) 실제로 코드가 정확한지 확인해보겠습니다. <완성된 최종 코드>

#include #include #include using namespace std; #define INF 1000000000 // 10억 int a, b; int input[8]; int seg[16]; int init(int node, int s, int e) { if (s == e) return seg[node] = input[s]; // start 와 end 의 위치가 일치하면 input[start] 값을 넣어준다. int mid = (s + e) / 2; return seg[node] = min(init(2 * node, s, mid), init(2 * node + 1, mid + 1, e)); // 다른 노드들의 정보를 } int query(int node, int s, int e, int l, int r) { if (e < l || r < s) return INF; // 찾아야하는 구간과 노드구간이 겹치지 않을 때 if (l <= s && e <= r) return seg[node]; // 찾아야하는 구간내에 노드구간이 포함될 때 int mid = (s + e) / 2; // 찾아야하는 구간이 노드구간에 포함되거나, 부분적으로 겹치는 경우 return min(query(2 * node, s, mid, l, r), query(2 * node + 1, mid + 1, e, l, r)); } int main() { for (int i = 0; i < 8; i++) { cin >> input[i]; } init(1, 0, 7); // 세그먼트 트리 만들기 cin >> a >> b; cout << query(1, 0, 7, a, b); } <실행 결과>

INDEX 0 1 2 3 4 5 6 7 input[ ] 7 3 2 6 5 8 1 4

이상입니다. 틀린 부분이 있거나 궁금하신 점을 댓글 부탁드리겠습니다. 읽어주셔서 감사드립니다!

반응형

구간 트리(Segment Tree)

구간 트리란?

구간 트리의 정체는 이진 트리입니다. 구간 트리 라는 이름은 그저 특정 용도로 사용되는 이진 트리의 한 형태를 나타낼 뿐입니다.

대게 구간 트리는 일차원 배열 상의 특정 구간에 대한 요청에 빠르게 대답하기 위해 사용합니다.

예를 들어, 1 2 3 4 5 라는 숫자 배열이 있다고 하겠습니다. 이 배열의 특정 구간의 합을 구한다고 할 때, 가장 간단한 방법은 그 특정 구간을 순회하면서 값을 더해나가는 겁니다. 이 경우 시간 복잡도는 O(n)이 됩니다.

만약 배열의 길이가 10억쯤 된다면 어떨까요? 컴퓨터가 1초에 1억번 정도의 루프를 돌린다고 하면 10초가 걸리겠네요.

그리고 또 이 합연산이 여러번 호출될 가능성이 있다면 어떨까요? 이 연산은 매번 합을 새로 구하기 때문에 문제가 됩니다.

구간 트리는 위와 같은 문제에 해법이 될 수 있습니다. log(n)의 시간 복잡도를 가지는 연산을 통해 한번만 구간 트리를 초기화하면 어떤 질의라도 log(n)의 복잡도로 해결할 수 있습니다.

순수하게 구간 트리를 이용해 답을 찾는 단계은 두 가지 과정을 거칩니다. 초기화 과정과 질의 과정입니다.

그리고 이외에 원본 배열이 수정될 경우 구간 트리 log(n)의 복잡도로 수정하는 과정이 존재합니다. 수정해야 될 부분이 많을 경우엔 그냥 구간 트리를 다시 초기화하는게 나을 수도 있지만, 수정되는 부분이 작은 경우에는 도움이 됩니다.

아래부터는 부분합을 구하는 문제에 대해 구간 트리를 구현해보겠습니다. 그럼 우선 초기화 과정부터~

구간 트리의 초기화

초기화 자체는 간단합니다.

구간을 반으로 나눠서 왼쪽 구간의 합은 왼쪽 자식 노드에 저장하고 오른쪽 구간의 합은 오른쪽 자식 노드에 저장. 그리고 현재 노드는 왼쪽 자식노드의 부분합 + 오른쪽 자식 노드 부분합 을 저장합니다.

/* left : 배열 범위의 왼쪽 right : 배열 범위의 오른쪽 node : segmentTree 배열 상의 노드(인덱스) 배열의 구간 합을 segmentTree에 저장. */ private static long initSegmentTree(int left, int right, int node) { if(left == right) return segmentTree[node] = numbers[left]; int mid = (left + right)/2; long leftSum = initSegmentTree(left, mid, 2*node); long rightSum = initSegmentTree(mid+1, right, 2*node+1); return segmentTree[node] = leftSum + rightSum; }

참고) 이진 트리에서는 노드를 일차원 배열로 나타낼 때 왼쪽, 오른쪽 자식 노드를 각각 2*node, 2*node+1로 나타낼 수 있습니다 .

구간 트리의 질의 처리

위 그림처럼 배열의 [3~5] 범위의 구간합을 구하려고 할 때, 이미 초기화 해둔 구간 트리를 이용할 수 있습니다.

일단 구현코드를 먼저 살펴보겠습니다.

/* targetLeft : 부분합을 찾기 위한 원본 배열 범위의 왼쪽 경계 targetLeft : 부분합을 찾기 위한 원본 배열 범위의 오른쪽 경계 node : 구간트리 배열의 노드(인덱스) nodeLeft : 노드에 해당하는 원본 배열 범위의 왼쪽 경계 nodeRight : 노드에 해당하는 원본 배열 범위의 오른쪽 경계 */ private static long querySum(int targetLeft, int targetRight, int node, int nodeLeft, int nodeRight) { //두 구간이 겹치지 않으면 무시한다. if(targetRight < nodeLeft || targetLeft > nodeRight) return 0; //node가 표현하는 범위가 target의 범위에 완전히 포함되는 경우 if(targetLeft <= nodeLeft && nodeRight <= targetRight) return segmentTree[node]; //겹치지만 완전히 포함하지 않는 경우 int mid = (nodeLeft+nodeRight)/2; long leftSum = querySum(targetLeft, targetRight, 2*node, nodeLeft, mid); long rightSum = querySum(targetLeft, targetRight, 2*node+1, mid+1, nodeRight); return leftSum + rightSum; } 위의 구현에서는 구간 트리를 1차원 배열에 표현했기 때문에 구간 트리 배열의 각 노드에는 부분합만 저장되어 있습니다. 하지만 개념적으로 각 노드는 해당 구간 정보를 가지고 있어야 합니다. 그래서 위 구현에서는 재귀함수 파라미터에 node, nodeLeft, nodeRight를 계산해서 넘기도록 하고 있습니다. 합을 구하는 방식은 원하는 구간(타겟 구간)과 해당 노드의 구간을 비교하는 것에서 시작됩니다. 1. 타겟 구간과 노드 구간이 전혀 겹치지 않는 경우 2. 타겟 구간에 노드 구간이 완전히 포함되는 경우 3. 타겟 구간에 노드 구간이 걸치는 경우 1의 경우는 합에서 제외할 것이기 때문에 0을 반환합니다. 2의 경우는 구간 노드에 저장된 값을 반환하고, 3의 경우는 다시 구간을 쪼갭니다. 구간 트리의 수정 배열의 하나의 값을 변경하는 경우, 다음과 같이 구간 트리를 수정할 수 있습니다. /* index : 수정하려고 하는 원본 배열 요소의 인덱스 newVal : 새로운 값 node : 구간 트리의 노드 인덱스 nodeLeft : 구간 트리 노드에 해당하는 원본 배열 범위의 왼쪽 경계 nodeLeft : 구간 트리 노드에 해당하는 원본 배열 범위의 오른쪽 경계 */ private static long update(int index, long newVal, int node, int nodeLeft, int nodeRight) { if(index < nodeLeft || index > nodeRight) return segmentTree[node]; if(nodeLeft == nodeRight) return segmentTree[node] = newVal; int mid = (nodeLeft+nodeRight)/2; long leftSum = update(index, newVal, 2*node, nodeLeft, mid); long rightSum = update(index, newVal, 2*node+1, mid+1, nodeRight); return segmentTree[node] = leftSum + rightSum; }

방식은 트리의 노드를 방문하면서 수정하려는 index가 포함되는 노드를 찾아서 재귀함수를 따라 리프까지 간 뒤,

값을 수정하고 재귀함수를 리턴하면서 합들을 수정하는 방식입니다.

세그먼트 트리 (구간 트리, Segment Tree)

☞ 세그먼트 트리란 이름 그대로 저장된 자료를 적절히 구간별로 전처리해 그들에 대한 질의들을 빠르게 대답할 수 있도록 해주는 트리입니다. 예를 들어 A={1,2,3,4,5}에서 [2,4] 구간의 최소치를 알고 싶다면 해당 배열을 순회하며 찾는 방법도 있지만, 해당 배열을 전처리해 세그먼트 트리를 생성해 더욱 더 빠르게 구현 할 수 있습니다.

A배열을 세그먼트 트리로 바꾼 후 -> 아래처럼 구간별로 나눠 세그먼트 트리를 만들 수 있다.

☞ 이렇게 이론적으로만 설명했지만, 코드 구현에 많은 어려움이 있을 수 있습니다.

그래서 세그먼트 트리 문제의 한 유형인 구간 최소 쿼리(range minimum query,RMQ)를 구현해보겠습니다.

※ 여기서 중요한 점은 세그먼트 트리에 초기 크기를 설정해줘야하는데 가장 이상적인 사이즈는 n을 2의 거듭제곱으로 올림한 뒤 2를 곱하는 사이즈입니다. 하지만 매번 이렇게 하면 귀찮으므로 메모리가 조금 낭비하더라도 4*n을 크기로 사용 할 수 있습니다.

구간을 초기화 할 때 구간 최소 쿼리이므로 각 노드에는 그 구간에 맞는 최소 값이 있어야 합니다. 따라서 아래 그림과 같이 세그먼트 트리를 만들어 줘야 합니다. (A= { 1, 2, 1, 2, 3, 1, 2, 3, 4})

☞ 소스 코드 (참고 : 프로그래밍 대회에서 배우는 알고리즘 문제해결 전략)

struct RMQ { int n; // 배열의 길이 vector rangeMin; // 각 구간의 최소치 RMQ(vector array) { n = array.size(); rangeMin.resize(n * 4); init(array, 0, n – 1, 1); } // 세그먼트 트리 초기 값 설정 int init(vector array, int left, int right, int node) { if (left == right) { return rangeMin[node] = array[left]; } int mid = (left + right) / 2; int leftMin = init(array, left, mid, node * 2); int rightMin = init(array, mid + 1, right, node * 2 + 1); return rangeMin[node] = min(leftMin, rightMin); } // 세그먼트 트리를 이용해 left, right 구간의 최소 값 도출하기 위한 함수 int query(int left, int right, int node, int nodeLeft, int nodeRight) { if (right < nodeLeft || left > nodeRight) return INF; if (left <= nodeLeft && nodeRight <= right) return rangeMin[node]; int mid = (nodeLeft + nodeRight) / 2; return min(query(left, right, node * 2, nodeLeft, mid), query(left, right, node * 2 + 1, mid + 1, nodeRight)); } // query함수를 위한 간략해 놓은 인터페이스 함수 int query(int left, int right) { return query(left, right, 1, 0, n - 1); } // 세그먼트 트리의 index의 값을 newValue 값으로 변경하기 위한 함수 int update(int index, int newValue, int node, int nodeLeft, int nodeRight) { if (index < nodeLeft || index > nodeRight) return rangeMin[node]; if (nodeLeft == nodeRight) return rangeMin[node] = newValue; int mid = (nodeLeft + nodeRight) / 2; return rangeMin[node] = min(update(index, newValue, node * 2, nodeLeft, mid), update(index, newValue, node * 2+1, mid + 1, nodeRight)); } //update함수를 위한 간략해 놓은 인터페이스 함수 int update(int index, int newValue) { return update(index, newValue, 1, 0, n – 1); } };

※ 함수 시간 복잡도

구간 트리 초기화 – init() : O(n)

구간 트리의 질의 처리 – query() : O(logn)

☞ RMQ 구현을 통해 세그먼트 트리의 원리에 대해 조금이나마 익숙해질 수 있을 것입니다. 이 RMQ 구조체만 잘 익힌다면 각 구간의 최대 값을 구하는 문제와 같은 세그먼트 트리를 활용한 문제를 쉽게 풀 수 있을 것입니다!

궁금하신 것이 있으시다면 댓글로 남겨주세요!~

반응형

So you have finished reading the 구간 트리 topic article, if you find this article useful, please share it. Thank you very much. See more: 세그먼트 트리, 백준 2357, 세그먼트 트리 파이썬, 백준 최대값, 펜윅 트리, Segment tree js, 히스토그램에서 가장 큰 직사각형

Leave a Comment