# 펜윅트리

  • 최하위 켜져있는 비트를 기반으로 트리를 만들어 동적배열에서 구간합을 효율적으로 구할 수 있는 자료구조
  • 구간 합을 구하는 쿼리, 값 갱신 작업을 O(logN) 만에 가능
  • 인덱스가 1부터 시작
  • 최하위 켜져있는 비트 = idx & -idx
  • 3(11)의 최하위 켜저있는 비트는 1(1), 4(100)의 최하위 켜져있는 비트는 4(100)

# 작동 원리

alt text

  • 각 블록에는 배열의 합들이 저장되어 있음

# 1. 구간 합

  • 1~2 의 합 = 2번 블록
  • 2~3 의 합 = 2번 + 3번 블록

# 2. 값 갱신

  • 3번 배열 값에 +val
  • 3번 배열 값은 블록 3, 4번에 영향을 미침
  • 그래서 우선 블록 3에 +val
  • 다음 인덱스 += (현재 인덱스)&-(현재 인덱스)
  • binary : 100 = 11 + (11 & 01)
  • 다음 인덱스인 4번 블록에 +val

# 코드

data = [3, 4, 10, 11]
n = len(data)
tree = [0] * (n + 1) # 1번 인덱스부터 시작해야 하므로


def range_update(index, value):
    global tree
    while index < len(tree):
        tree[index] += value
        index += index & -index


def _sum(index):
    ret = 0
    while index > 0:
        ret += tree[index]
        index -= index & -index
    return ret


def range_query(left, right):
    return _sum(right) - _sum(left - 1)


for i in range(n):
    range_update(i + 1, data[i])

print(tree) # [0, 3, 7, 10, 28]

print(range_query(1, 2)) # 7
print(range_query(2, 4)) # 25

range_update(2, 5)
print(tree) # [0, 3, 12, 10, 33]

print(range_query(1, 2)) # 12
print(range_query(2, 4)) # 30