일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Python
- 삼성소프트웨어멤버십
- hopfield network
- 물걸레자동세척로봇청소기
- 멤버십
- BAM
- Bidirectional Associative Memory
- SSM
- 갤럭시탭S8울트라
- 인공지능
- 빅데이터
- 패턴인식
- 물걸레로봇청소기추천
- 파이썬
- 나르왈프레오
- 패턴 인식
- 증강현실
- NarwalFreo
- 신경망
- 삼성전자 소프트웨어멤버십 SSM
- Google App Engine
- 하이퍼바이저
- 구글 앱 엔진
- Neural Network
- 가상화
- 고려대학교
- Friendship
- 삼성
- 신경회로망
- 동아리
- Today
- Total
정보공간_1
[6기 강남 조유석] Binary Indexed Tree 본문
안녕하세요. 강남멤버십 23-1기 조유석입니다.
이번 포스팅에서는 빠르고 간단하게 구간 합을 구하는데 사용되는 Binary Indexed Tree 에 대해 알아보겠습니다.
Segment Tree
Binary Indexed Tree 를 보기 전 먼저 Segment Tree 에 대해 간단히 살펴보겠습니다.
세그먼트 트리는 특정 구간에 대한 질문을 빠르게 답하는 데 사용합니다. 아래와 같은 특징을 가지며, 아래 그림과 같은 데이터 구조를 가집니다.
- 완전 이진트리
- 각 노드는 자신이 가지고 있는 구간에 대한 정보를 가짐
- 각 노드의 자식 노드는 부모 노드의 구간을 이등분한 두 개의 구간 중 한쪽 구간에 대한 정보를 가짐
- 구간에 대한 조작을 O(log n)로 실행
세그먼트 트리의 기본적인 아이디어는 주어진 배열의 구간들을 표현하는 이진트리를 만드는 것이며, 이러한 전처리 과정을 수행해 두면 어떤 구간 [i,j]가 주어지더라도 이 구간을 세그먼트 트리의 노드에 포함된 구간들의 합집합으로 표현할 수 있습니다.
예를 들어, [2,8] 구간은 그림에 진하게 칠해진 세 구간 [2], [3,4], [5,8] 의 합집합으로 표현할 수 있습니다.
Binary Indexed Tree(or Fenwik Tree)
세그먼트 트리의 가장 흔한 사용 예는 구간 합을 빠르게 구하는 것이고, 이 경우 세그먼트 트리 대신 쓸 수 있는 구간 트리의 궁극적인 진화 형태로 펜윅 트리(Fenwick Tree) 혹은 이진 인덱스 트리(Binary Indexed Tree)라고 불립니다.
s부터 t까지의 합을 구하고자 할 때, 세그먼트 트리를 사용하면 직접적으로 구할 수 있습니다. 하지만 합의 경우에는 (1부터 t까지의 합) - (1부터 s-1까지의 합)을 계산한다면, s부터 t까지의 합이 됩니다. 따라서, 임의의 i에 대해서는 1부터 i까지의 합을 계산할 수 있다면 충분하다는 것을 알 수 있습니다. 이와 같은 조건을 제한한다면 세그먼트 트리의 오른쪽 방향으로 분기되어 있는 노드의 값이 필요 없어집니다. 이러한 방법을 기반으로 한 자료 구조가 Binary Indexed Tree 이며 세그먼트 트리보다 구현이 쉽고, 고속으로 동작합니다.
- 뒷자리가 1로 끝나는 1, 3, 5, 7은 길이가 1
- 뒷자리가 1개의 0인 2, 6은 길이가 2
- 뒷자리가 2개의 0인 4는 길이가 4
- …
Binary Indexed Tree에서는 이러한 특성을 이용해 각각의 조작을 간단한 비트연산으로 작성할 수 있습니다.
먼저, Binary Indexed Tree에서 n번째 원소까지의 부분합을 구하는 과정을 살펴보겠습니다.
예를 들어, 7까지의 합을 구하하기 위해 4, 6, 7 번째 원소의 합을 구해야 하며 그 과정을 보면 다음과 같습니다.
각 과정에서 맨 오른쪽에 있는 1 비트를 빼줌으로서 다음 과정으로 진행됩니다.
다음으로 Binary Indexed Tree에서 n번째 원소에 값을 더하거나 빼는 경우를 살펴보겠습니다.
예를 들어, 5번째 원소의 값을 더하거나 뺄 경우 변경해야 할 원소는 5, 6, 8 이며 그 과정을 이진수로 표현하면 다음과 같습니다.
부분합을 구할 때와는 반대로 맨 오른쪽에 있는 1 비트를 더해줌으로서 다음 과정으로 진행됩니다.
컴퓨터가 음수를 표현하기 위해 2의 보수를 사용한다는 점을 이용하여 맨 오른쪽 1비트를 찾는 것을 (idx & -idx)와 같이 간단하게 구현할 수 있으며 이를 이용해 부분합을 계산하는 sum() 함수, Binary Indexed Tree 를 갱신하는 add()함수를 아래와 같이 구현할 수 있습니다.
이 두 연산에서 반복문이 수행될 때마다 트리의 한 층을 올라가는데, 트리의 높이는 항상 O(log n) 이기 때문에, 이 두연산의 시간복잡도는 모두 O(log n)입니다.
Binary Indexed Tree 의 구현은 엄청나게 간결하기 때문에, 계속 변하는 배열의 구간 합을 구할 때는, 세그먼트 트리보다 자주 사용하게 됩니다.
최근에는 ACM-ICPC Asia Regional Daejeon Site 2013 에서 Binary Indexed Tree 를 이용해 푸는 문제가 출제되었습니다.(Problem I: Permutation Graphs)
http://acm.kaist.ac.kr/2013/MainContest/problemset.pdf
공부하고 풀어보는 것도 좋을 것 같습니다.
이상으로 Binary Indexed Tree 에 대해 알아보았습니다.
앞으로 문제해결을 위한 자료구조, 알고리즘 몇 가지를 더 알아보겠습니다.
감사합니다.
Reference
- ‘프로그래밍 대회에서 배우는 알고리즘 문제해결 전략’ - 구종만 저
- ‘프로그래밍 콘테스트 챌린징’ - Takuya Akiba, Yoichi Iwata, Masatoshi Kitagawa 저
'IT 놀이터 > Elite Member Tech & Talk' 카테고리의 다른 글
[6기 신촌 류보원] 체감형 게임 (0) | 2014.08.08 |
---|---|
[6기 수원 정재윤] Hardware 기초 #1 _ 하드웨어의 다홍치마 프레임 설계 (0) | 2014.08.08 |
[6기 대구 류지현] Window Device Driver #1 (0) | 2014.08.08 |
[6기 신촌 김윤상] R 언어 #1 - Data Analysis에 최적화된 R 언어 알아보기 (0) | 2014.08.08 |
[6기 강북 전영진] 리눅스 커널 심층 분석 #0 (0) | 2014.08.07 |