Дерево отрезков: различия между версиями

Материал из Олимпиадное программирование в УлГТУ
Перейти к навигации Перейти к поиску
Нет описания правки
Строка 115: Строка 115:
     t[v] = t[2 * v + 1] + t[2 * v + 2];
     t[v] = t[2 * v + 1] + t[2 * v + 2];
  }
  }
== Ссылки на задачи ==
* [http://codeforces.ru/gym/100094/problem/A Codeforces #100094.A — Это как пятый, но на один пониже] (Запрос значения, покраска на отрезке + бинарный поиск)
:* [http://codeforces.ru/gym/100249/problem/D Codeforces #100249.D — Экзамен]
* [http://codeforces.ru/gym/100094/problem/B Codeforces #100094.B — Грибы] (Базовая реализация — запрос максимума)
* [http://codeforces.ru/gym/100094/problem/C Codeforces #100094.C — Художник] (Запрос суммы, покраска на отрезке + требуется поддерживать дополнительные значения в вершинах)
:* [http://codeforces.ru/gym/100255/problem/C Codeforces #100255.C — Художник]
* [http://codeforces.ru/gym/100255/problem/B Codeforces #100255.B — Большая стена] (Базовая реализация — запрос максимума, добавление на отрезке)
* [http://codeforces.ru/gym/100094/problem/E Codeforces #100094.E — Золотые рудники] (Запрос максимума, добавление на отрезке + sweep line)
:* [http://codeforces.ru/gym/100099/problem/B Codeforces #100099.B — Золотые рудники]


== Ссылки ==
== Ссылки ==
Теория:
* [http://e-maxx.ru/algo/segment_tree e-maxx.ru — Дерево отрезков]
* [http://e-maxx.ru/algo/segment_tree e-maxx.ru — Дерево отрезков]
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%B0%D1%8F_%D0%BC%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B8_%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85#.D0.94.D0.B5.D1.80.D0.B5.D0.B2.D0.BE_.D0.BE.D1.82.D1.80.D0.B5.D0.B7.D0.BA.D0.BE.D0.B2 neerc.ifmo.ru/wiki — Дерево отрезков]
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%B0%D1%8F_%D0%BC%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B8_%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85#.D0.94.D0.B5.D1.80.D0.B5.D0.B2.D0.BE_.D0.BE.D1.82.D1.80.D0.B5.D0.B7.D0.BA.D0.BE.D0.B2 neerc.ifmo.ru/wiki — Дерево отрезков]
* [http://informatics.mccme.ru/course/view.php?id=18 informatics.mccme.ru — Курс «Структуры данных» — часть 5]
Демонстрация:
* [http://visualgo.net/segmenttree.html VisuAlgo — Segment Tree]
* [http://visualgo.net/segmenttree.html VisuAlgo — Segment Tree]
Код:
* [http://github.com/indy256/codelibrary/blob/master/java/src/SegmentTree.java CodeLibrary — Segment tree]
* [http://github.com/indy256/codelibrary/blob/master/java/src/SegmentTree.java CodeLibrary — Segment tree]
* [http://github.com/ADJA/algos/blob/master/DataStructures/SegmentTree(Assign-Sum).cpp Algos — Segment Tree (Assign-Sum)]
* [http://github.com/ADJA/algos/blob/master/DataStructures/SegmentTree(Assign-Sum).cpp Algos — Segment Tree (Assign-Sum)]
* [http://github.com/ADJA/algos/blob/master/DataStructures/ImplicitSegmentTree.cpp Algos — Implicit segment tree]
Задачи:
* [http://informatics.mccme.ru/course/view.php?id=18 informatics.mccme.ru — Курс «Структуры данных» — часть 5]
* [http://opentrains.mipt.ru/zksh/files/zksh2015/lectures/zksh_segtree_tasks_C.pdf Задачи Зимней школы МФТИ]
* [[:Категория:Задачи: Дерево отрезков|Задачи: Дерево отрезков]]


[[Category:Структуры данных для задач RSQ/RMQ]]
[[Category:Структуры данных для задач RSQ/RMQ]]

Версия от 20:50, 7 июля 2015

Запрос на отрезке и модификация отдельных элементов

  • Если отрезок текущей вершины не пересекается с отрезком запроса, то возвращается нейтральное значение.
  • Если отрезок текущей вершины целиком включён в отрезок запроса, то возвращается значение, хранящееся в текущей вершине.
  • Во всех остальных случаях запрос перенаправляется потомкам текущей вершины.

Можно выделить два распространённых способа реализации данной логики:

if (r < vl || vr < l)
    //отрезки не пересекаются
if (l <= vl && vr <= r)
    //отрезок текущей вершины принадлежит отрезку запроса
query(2 * v + 1, vl, vm, l, r);
query(2 * v + 2, vm + 1, vr, l, r);
 
if (l > r)
    //отрезки не пересекаются
if (l == vl && vr == r)
    //отрезок текущей вершины принадлежит отрезку запроса
query(2 * v + 1, vl, vm, l, min(r, vm));
query(2 * v + 2, vm + 1, vr, max(l, vm + 1), r);
int t[4 * 100010];

void build(int v, int vl, int vr, int a[]) {
    if (vl == vr) {
        t[v] = a[vl];
        return;
    }
    int vm = vl + (vr - vl) / 2;
    build(2 * v + 1, vl, vm, a);
    build(2 * v + 2, vm + 1, vr, a);
    t[v] = t[2 * v + 1] + t[2 * v + 2];
}

int query(int v, int vl, int vr, int l, int r) {
    if (r < vl || vr < l)
        return 0;
    if (l <= vl && vr <= r)
        return t[v];
    int vm = vl + (vr - vl) / 2;
    int ql = query(2 * v + 1, vl, vm, l, r);
    int qr = query(2 * v + 2, vm + 1, vr, l, r);
    return ql + qr;
}

void modify(int v, int vl, int vr, int pos, int val) {
    if (pos < vl || vr < pos)
        return;
    if (pos == vl && vl == vr) {
        t[v] += val;
        return;
    }
    int vm = vl + (vr - vl) / 2;
    modify(2 * v + 1, vl, vm, pos, val);
    modify(2 * v + 2, vm + 1, vr, pos, val);
    t[v] = t[2 * v + 1] + t[2 * v + 2];
}

Запрос на отрезке и модификация на отрезке

  • Считаем, что актуальное значение в вершине v равно t[v] + add[v] * (vr - vl + 1).
  • Перед выводом результата или передачей запроса будем спускать значение add[v] потомкам текущей вершины при помощи функции push().
int t[4 * 100010], add[4 * 100010];

void push(int v, int vl, int vr) {
    if (vl != vr) {
        add[2 * v + 1] += add[v];
        add[2 * v + 2] += add[v];         
    }
    t[v] += add[v] * (vr - vl + 1);
    add[v] = 0;
}

void build(int v, int vl, int vr, int a[]) {
    if (vl == vr) {
        t[v] = a[vl];
        return;
    }
    int vm = vl + (vr - vl) / 2;
    build(2 * v + 1, vl, vm, a);
    build(2 * v + 2, vm + 1, vr, a);
    t[v] = t[2 * v + 1] + t[2 * v + 2];
}

int query(int v, int vl, int vr, int l, int r) {
    push(v, vl, vr);
    if (r < vl || vr < l)
        return 0;     
    if (l <= vl && vr <= r)
        return t[v];
    int vm = vl + (vr - vl) / 2;
    int ql = query(2 * v + 1, vl, vm, l, r);
    int qr = query(2 * v + 2, vm + 1, vr, l, r);
    return ql + qr;
}

void modify(int v, int vl, int vr, int l, int r, int val) {
    push(v, vl, vr);
    if (r < vl || vr < l)
        return;
    if (l <= vl && vr <= r) {
        add[v] += val;
        push(v, vl, vr);
        return;
    }
    int vm = vl + (vr - vl) / 2;
    modify(2 * v + 1, vl, vm, l, r, val);
    modify(2 * v + 2, vm + 1, vr, l, r, val);
    t[v] = t[2 * v + 1] + t[2 * v + 2];
}

Ссылки

Теория:

Демонстрация:

Код:

Задачи: