← Назад к структурам данных

Дерево Фенвика

Бинарное индексированное дерево для префиксных запросов и обновлений за O(log n)

🐍 Python (реализация)
n = int(input())
A = list(map(int, input().split()))
F = [0] * (n + 1)

def get(r):
    z = 0
    while r > 0:
        z += F[r]
        r -= r & -r
    return z

def add(p, z):
    while p <= n:
        F[p] += z
        p += p & -p

def upd(p, z):
    d = z - A[p - 1]
    A[p - 1] = z
    add(p, d)

def tree():
    for i in range(1, n + 1):
        add(i, A[i - 1])

tree()
m = int(input())

for _ in range(m):
    s = input().split()
    if s[0] == "s":
        l, r = int(s[1]), int(s[2])
        print(get(r) - get(l - 1), end=" ")
    elif s[0] == "u":
        p, z = int(s[1]), int(s[2])
        upd(p, z)
    else:
        p, z = int(s[1]), int(s[2])
        add(p, z)
⚙️ C++ (реализация)
#include <bits/stdc++.h>
using namespace std;

int n;
vector<int> A, F;

int get(int r) {
    int z = 0;
    while (r > 0) {
        z += F[r];
        r -= r & -r;
    }
    return z;
}

void add(int p, int z) {
    while (p <= n) {
        F[p] += z;
        p += p & -p;
    }
}

void upd(int p, int z) {
    int d = z - A[p - 1];
    A[p - 1] = z;
    add(p, d);
}

void build() {
    for (int i = 1; i <= n; i++) {
        add(i, A[i - 1]);
    }
}

int main() {
    cin >> n;
    A.resize(n);
    F.assign(n + 1, 0);
    
    for (int i = 0; i < n; i++) {
        cin >> A[i];
    }
    
    build();
    
    int m;
    cin >> m;
    
    for (int i = 0; i < m; i++) {
        string s;
        cin >> s;
        if (s == "s") {
            int l, r;
            cin >> l >> r;
            cout << get(r) - get(l - 1) << " ";
        } else if (s == "u") {
            int p, z;
            cin >> p >> z;
            upd(p, z);
        } else {
            int p, z;
            cin >> p >> z;
            add(p, z);
        }
    }
    
    return 0;
}

Как работает дерево Фенвика?

Дерево Фенвика (Binary Indexed Tree) — это структура данных, которая позволяет выполнять два типа операций за O(log n):

Основная идея

Каждый индекс i в дереве Фенвика хранит сумму не одного элемента, а диапазона элементов. Размер диапазона определяется младшим единичным битом числа i (операция i & -i).

Ключевая операция: i & -i — возвращает младший единичный бит числа i.
Пример: для i=6 (110₂) → 2 (010₂)

Основные операции

Сложность операций: O(log n) — количество итераций равно количеству битов в числе.

Пространственная сложность: O(n) — массив размера n+1.

Формат ввода и вывода

Построение дерева:

Запросы (m — количество запросов):

Пример ввода:

5
1 2 3 4 5
4
s 1 3
a 2 2
s 1 3
u 3 10
s 1 5

Вывод: 6 8 21

(сумма [1,3]=6, после добавления A[2]+=2 → массив [1,4,3,4,5], сумма[1,3]=8, после замены A[3]=10 → массив [1,4,10,4,5], сумма[1,5]=24)

Попробовать дерево Фенвика онлайн

Введите массив и выполните запросы:

Результат появится здесь...