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

Материал из Олимпиадное программирование в УлГТУ
Перейти к навигации Перейти к поиску
Нет описания правки
 
(не показано 11 промежуточных версий этого же участника)
Строка 1: Строка 1:
== Ссылки на задачи ==
== TLDR ==
* [http://codeforces.ru/gym/100070/problem/J Codeforces #100070.J — Range Minimum Query]
<youtube width="300" height="180">MLIbII4sBs0</youtube>
<youtube width="300" height="180">mkpeHhmmUPw</youtube>
 
== Multimap с getMinValue ==
{|width=100%
|width=50%|
'''getMinValue(lKey, rKey)'''
class Treap {
    inline static minstd_rand gen;
    struct Node {
        int key, priority, value, minValue;
        Node *left = 0, *right = 0;
        Node(int key, int value) : key(key), priority(gen()), value(value), minValue(value) {}
    } *root = 0;
    int getMinValue(Node *n) const {
        return n ? n->minValue : 2e9;
    }
    void update(Node *n) {
        if (n)
            n->minValue = min({ getMinValue(n->left), n->value, getMinValue(n->right) });
    }
    Node *merge(Node *a, Node *b) {
        if (!a || !b)
            return a ? a : b;
        if (a->priority > b->priority) {
            a->right = merge(a->right, b);
            update(a);
            return a;
        } else {
            b->left = merge(a, b->left);
            update(b);
            return b;
        }
    }
    void split(Node *t, int key, Node *&a, Node *&b) {
        if (!t) {
            a = b = 0;
            return;
        }
        if (t->key < key) {
            split(t->right, key, t->right, b);
            a = t;
        } else {
            split(t->left, key, a, t->left);
            b = t;
        }
        update(a);
        update(b);
    }
public:
    void insert(int key, int value) {
        Node *a, *b;
        split(root, key, a, b);
        root = merge(a, merge(new Node(key, value), b));
    }
    void erase(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        root = merge(a, c);
    }
    void eraseOne(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        if (b)
            b = merge(b->left, b->right);
        root = merge(a, merge(b, c));
    }
    int getMinValue(int lKey, int rKey) {
        Node *a, *b, *c;
        split(root, lKey, a, b);
        split(b, rKey + 1, b, c);
        int res = getMinValue(b);
        root = merge(a, merge(b, c));
        return res;
    }
};
|width=50%|
'''getMinValue(lIndex, rIndex)'''
class Treap {
    inline static minstd_rand gen;
    struct Node {
        int key, priority, size = 1, value, minValue;
        Node *left = 0, *right = 0;
        Node(int key, int value) : key(key), priority(gen()), value(value), minValue(value) {}
    } *root = 0;
    int getSize(Node *n) const {
        return n ? n->size : 0;
    }
    int getMinValue(Node *n) const {
        return n ? n->minValue : 2e9;
    }
    void update(Node *n) {
        if (n) {
            n->size = getSize(n->left) + 1 + getSize(n->right);
            n->minValue = min({ getMinValue(n->left), n->value, getMinValue(n->right) });
        }
    }
    Node *merge(Node *a, Node *b) {
        if (!a || !b)
            return a ? a : b;
        if (a->priority > b->priority) {
            a->right = merge(a->right, b);
            update(a);
            return a;
        } else {
            b->left = merge(a, b->left);
            update(b);
            return b;
        }
    }
    void split(Node *t, int key, Node *&a, Node *&b) {
        if (!t) {
            a = b = 0;
            return;
        }
        if (t->key < key) {
            split(t->right, key, t->right, b);
            a = t;
        } else {
            split(t->left, key, a, t->left);
            b = t;
        }
        update(a);
        update(b);
    }
    void splitByIndex(Node *t, int index, Node *&a, Node *&b) {
        if (!t) {
            a = b = 0;
            return;
        }
        int leftSize = getSize(t->left);
        if (leftSize < index) {
            splitByIndex(t->right, index - leftSize - 1, t->right, b);
            a = t;
        } else {
            splitByIndex(t->left, index, a, t->left);
            b = t;           
        }
        update(a);
        update(b);
    }
public:
    void insert(int key, int value) {
        Node *a, *b;
        split(root, key, a, b);
        root = merge(a, merge(new Node(key, value), b));
    }
    void erase(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        root = merge(a, c);
    }
    void eraseOne(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        if (b)
            b = merge(b->left, b->right);
        root = merge(a, merge(b, c));
    }
    int getMinValue(int lIndex, int rIndex) {
        Node *a, *b, *c;
        splitByIndex(root, lIndex, a, b);
        splitByIndex(b, rIndex - lIndex + 1, b, c);
        int res = getMinValue(b);
        root = merge(a, merge(b, c));
        return res;
    }
};
|}
 
== Multiset с indexOf(key), operator[], lessCount(key), greaterCount(key) ==
{|width=100%
|width=50%|
'''Одинаковые элементы хранятся в нескольких узлах'''
class Treap {
    inline static minstd_rand gen;
    struct Node {
        int key, priority, size = 1;
        Node *left = 0, *right = 0;
        Node(int key) : key(key), priority(gen()) {}
    } *root = 0;
    int getSize(Node *n) const {
        return n ? n->size : 0;
    }
    void update(Node *n) {
        if (n)
            n->size = getSize(n->left) + 1 + getSize(n->right);
    }
    Node *merge(Node *a, Node *b) {
        if (!a || !b)
            return a ? a : b;
        if (a->priority > b->priority) {
            a->right = merge(a->right, b);
            update(a);
            return a;
        } else {
            b->left = merge(a, b->left);
            update(b);
            return b;
        }
    }
    void split(Node *t, int key, Node *&a, Node *&b) {
        if (!t) {
            a = b = 0;
            return;
        }
        if (t->key < key) {
            split(t->right, key, t->right, b);
            a = t;
        } else {
            split(t->left, key, a, t->left);
            b = t;
        }
        update(a);
        update(b);
    }
    int indexOf(Node *n, int key) const {
        if (!n)
            return 0;
        else if (key < n->key)
            return indexOf(n->left, key);
        else if (n->key == key)
            return getSize(n->left);
        else
            return getSize(n->left) + 1 + indexOf(n->right, key);
    }
    int getByIndex(Node *n, int index) const {
        int leftSize = getSize(n->left);
        if (leftSize > index)
            return getByIndex(n->left, index);
        else if (leftSize == index)
            return n->key;
        else
            return getByIndex(n->right, index - leftSize - 1);
    }
public:
    int size() const {
        return getSize(root);
    }
    int indexOf(int key) const {
        return indexOf(root, key);
    }
    int operator[](int index) const {
        return getByIndex(root, index);
    }
    void insert(int key) {
        Node *a, *b;
        split(root, key, a, b);
        root = merge(a, merge(new Node(key), b));
    }
    void erase(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        root = merge(a, c);
    }
    void eraseOne(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        if (b)
            b = merge(b->left, b->right);
        root = merge(a, merge(b, c));
    }
    int lessCount(int key) {
        Node *a, *b;
        split(root, key, a, b);
        int res = getSize(a);
        root = merge(a, b);
        return res;
    }
    int lessEqualCount(int key) {
        Node *a, *b;
        split(root, key + 1, a, b);
        int res = getSize(a);
        root = merge(a, b);
        return res;
    }
    int greaterCount(int key) {
        Node *a, *b;
        split(root, key + 1, a, b);
        int res = getSize(b);
        root = merge(a, b);
        return res;
    }
    int greaterEqualCount(int key) {
        Node *a, *b;
        split(root, key, a, b);
        int res = getSize(b);
        root = merge(a, b);
        return res;
    }
};
|width=50%|
'''Одинаковые элементы хранятся в одном узле'''
class Treap {
    inline static minstd_rand gen;
    struct Node {
        int key, priority, nodeSize = 1, subtreeSize = 1;
        Node *left = 0, *right = 0;
        Node(int key) : key(key), priority(gen()) {}
    } *root = 0;
    int getSubtreeSize(Node *n) const {
        return n ? n->subtreeSize : 0;
    }
    void update(Node *n) {
        if (n)
            n->subtreeSize = getSubtreeSize(n->left) + n->nodeSize + getSubtreeSize(n->right);
    }
    Node *merge(Node *a, Node *b) {
        if (!a || !b)
            return a ? a : b;
        if (a->priority > b->priority) {
            a->right = merge(a->right, b);
            update(a);
            return a;
        } else {
            b->left = merge(a, b->left);
            update(b);
            return b;
        }
    }
    void split(Node *t, int key, Node *&a, Node *&b) {
        if (!t) {
            a = b = 0;
            return;
        }
        if (t->key < key) {
            split(t->right, key, t->right, b);
            a = t;
        } else {
            split(t->left, key, a, t->left);
            b = t;
        }
        update(a);
        update(b);
    }
    int indexOf(Node *n, int key) const {
        if (!n)
            return 0;
        else if (key < n->key)
            return indexOf(n->left, key);
        else if (n->key == key)
            return getSubtreeSize(n->left);
        else
            return getSubtreeSize(n->left) + n->nodeSize + indexOf(n->right, key);
    }
    int getByIndex(Node *n, int index) const {
        int leftSize = getSubtreeSize(n->left);
        if (leftSize > index)
            return getByIndex(n->left, index);
        else if (leftSize + n->nodeSize >= index)
            return n->key;
        else
            return getByIndex(n->right, index - leftSize - n->nodeSize);
    }
public:
    int size() const {
        return getSubtreeSize(root);
    }
    int indexOf(int key) const {
        return indexOf(root, key);
    }
    int operator[](int index) const {
        return getByIndex(root, index);
    }
    void insert(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        if (b) {
            b->nodeSize++;
            b->subtreeSize++;
        } else {
            b = new Node(key);
        }
        root = merge(a, merge(b, c));
    }
    void erase(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        root = merge(a, c);
    }
    void eraseOne(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        if (b) {
            b->nodeSize--;
            b->subtreeSize--;
            if (!b->nodeSize)
                b = 0;
        }
        root = merge(a, merge(b, c));
    }
    int lessCount(int key) {
        Node *a, *b;
        split(root, key, a, b);
        int res = getSize(a);
        root = merge(a, b);
        return res;
    }
    int lessEqualCount(int key) {
        Node *a, *b;
        split(root, key + 1, a, b);
        int res = getSize(a);
        root = merge(a, b);
        return res;
    }
    int greaterCount(int key) {
        Node *a, *b;
        split(root, key + 1, a, b);
        int res = getSize(b);
        root = merge(a, b);
        return res;
    }
    int greaterEqualCount(int key) {
        Node *a, *b;
        split(root, key, a, b);
        int res = getSize(b);
        root = merge(a, b);
        return res;
    }
};
|}
 
== Set с find_by_order(index) и order_of_key(key) через __gnu_pbds ==
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using ordered_set = tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>;
 
* [http://codeforces.com/contest/61/submission/61118877 Пример решения]
* [https://codeforces.com/blog/entry/11080 Codeforces — C++ STL: Policy based data structures]
 
 
== Vector ==
{|width=100%
|width=50%|
'''getMinValue(lIndex, rIndex)'''
class ImplicitTreap {
    inline static minstd_rand gen;
    struct Node {
        int value, priority, size = 1, minValue;
        Node *left = 0, *right = 0;
        Node(int value) : value(value), priority(gen()), minValue(value) {}
    } *root = 0;
    int getSize(Node *n) {
        return n ? n->size : 0;
    }
    int getMinValue(Node *n) {
        return n ? n->minValue : 2e9;
    }
    void update(Node *n) {
        if (n) {
            n->size = getSize(n->left) + 1 + getSize(n->right);
            n->minValue = min({ getMinValue(n->left), n->value, getMinValue(n->right) });
        }
    }
    Node *merge(Node *a, Node *b) {
        if (!a || !b)
            return a ? a : b;
        if (a->priority > b->priority) {
            a->right = merge(a->right, b);
            update(a);
            return a;
        } else {
            b->left = merge(a, b->left);
            update(b);
            return b;
        }
    }
    void split(Node *t, int k, Node *&a, Node *&b) {
        if (!t) {
            a = b = 0;
            return;
        }
        if (getSize(t->left) < k) {
            split(t->right, k - getSize(t->left) - 1, t->right, b);
            a = t;
        } else {
            split(t->left, k, a, t->left);
            b = t;
        }
        update(a);
        update(b);
    }
public:
    void pushBack(int value) {
        root = merge(root, new Node(value));
    }
    void pushFront(int value) {
        root = merge(new Node(value), root);
    }
    void insertAfter(int index, int value) {
        Node *a, *b;
        split(root, index, a, b);
        root = merge(a, merge(new Node(value), b));
    }
    void erase(int index) {
        Node *a, *b, *c;
        split(root, index, a, b);
        split(b, 1, b, c);
        root = merge(a, c);
    }
    void erase(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        root = merge(a, c);
    }
    int operator[](int index) {
        Node *a, *b, *c;
        split(root, index, a, b);
        split(b, 1, b, c);
        int res = b->value;
        root = merge(a, merge(b, c));
        return res;
    }
    void moveToFront(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        root = merge(b, merge(a, c));
    }
    void moveToBack(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        root = merge(a, merge(c, b));
    }
    int getMinValue(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        int res = getMinValue(b);
        root = merge(a, merge(b, c));
        return res;
    }
};
|width=50%|
'''reverse(lIndex, rIndex)'''
class ImplicitTreap {
    inline static minstd_rand gen;
    struct Node {
        int value, priority, size = 1, rev = 0;
        Node *left = 0, *right = 0;
        Node(int value) : value(value), priority(gen()) {}
    } *root = 0;
    int getSize(Node *n) {
        return n ? n->size : 0;
    }
    void push(Node *n) {
        if (n && n->rev) {
            swap(n->left, n->right);
            if (n->left)
                n->left->rev ^= 1;
            if (n->right)
                n->right->rev ^= 1;
            n->rev = 0;
        }
    }
    void update(Node *n) {
        if (n)
            n->size = getSize(n->left) + 1 + getSize(n->right);
    }
    Node *merge(Node *a, Node *b) {
        push(a);
        push(b);
        if (!a || !b)
            return a ? a : b;
        if (a->priority > b->priority) {
            a->right = merge(a->right, b);
            update(a);
            return a;
        } else {
            b->left = merge(a, b->left);
            update(b);
            return b;
        }
    }
    void split(Node *t, int k, Node *&a, Node *&b) {
        push(t);
        if (!t) {
            a = b = 0;
            return;
        }
        if (getSize(t->left) < k) {
            split(t->right, k - getSize(t->left) - 1, t->right, b);
            a = t;
        } else {
            split(t->left, k, a, t->left);
            b = t;
        }
        update(a);
        update(b);
    }
public:
    void pushBack(int value) {
        root = merge(root, new Node(value));
    }
    void pushFront(int value) {
        root = merge(new Node(value), root);
    }
    void insertAfter(int index, int value) {
        Node *a, *b;
        split(root, index, a, b);
        root = merge(a, merge(new Node(value), b));
    }
    void erase(int index) {
        Node *a, *b, *c;
        split(root, index, a, b);
        split(b, 1, b, c);
        root = merge(a, c);
    }
    void erase(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        root = merge(a, c);
    }
    int operator[](int index) {
        Node *a, *b, *c;
        split(root, index, a, b);
        split(b, 1, b, c);
        int res = b->value;
        root = merge(a, merge(b, c));
        return res;
    }
    void moveToFront(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        root = merge(b, merge(a, c));
    }
    void moveToBack(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        root = merge(a, merge(c, b));
    }
    void reverse(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        b->rev = 1;
        root = merge(a, merge(b, c));
    }
};
|}


== Ссылки ==
== Ссылки ==
Теория:
* [https://www.youtube.com/watch?v=MLIbII4sBs0&list=PLGhUJWLZ8uQ5Ewplzb1ER29p4-kQme5Yr&index=5 Фолунин В. — Декартово дерево по неявному ключу]
* [http://e-maxx.ru/algo/treap#7 e-maxx.ru &mdash; Неявные декартовы деревья]
* [http://e-maxx.ru/algo/treap#7 e-maxx.ru &mdash; Неявные декартовы деревья]
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B5%D0%BA%D0%B0%D1%80%D1%82%D0%BE%D0%B2%D0%BE_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BF%D0%BE_%D0%BD%D0%B5%D1%8F%D0%B2%D0%BD%D0%BE%D0%BC%D1%83_%D0%BA%D0%BB%D1%8E%D1%87%D1%83 neerc.ifmo.ru/wiki &mdash; Декартово дерево по неявному ключу]
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B5%D0%BA%D0%B0%D1%80%D1%82%D0%BE%D0%B2%D0%BE_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BF%D0%BE_%D0%BD%D0%B5%D1%8F%D0%B2%D0%BD%D0%BE%D0%BC%D1%83_%D0%BA%D0%BB%D1%8E%D1%87%D1%83 neerc.ifmo.ru/wiki &mdash; Декартово дерево по неявному ключу]
* [http://habrahabr.ru/post/102364/ habrahabr.ru &mdash; Декартово дерево: Часть 3. Декартово дерево по неявному ключу]
* [http://habrahabr.ru/post/102364/ habrahabr.ru &mdash; Декартово дерево: Часть 3. Декартово дерево по неявному ключу]
* [http://opentrains.mipt.ru/zksh/files/zksh2015/lectures/zksh_cartesian.pdf Иващенко Д., Семенов К. Декартово дерево]
Код:
* [https://github.com/indy256/codelibrary/blob/master/cpp/structures/treap_indexed.cpp github.com/indy256/codelibrary/blob/master/cpp/structures/treap_indexed.cpp]
* [http://github.com/ADJA/algos/blob/master/DataStructures/CartesianTreeImplicitKeys.cpp Algos &mdash; Cartesian tree using implicit keys]
Задачи:
* [http://informatics.mccme.ru/course/view.php?id=18 informatics.mccme.ru &mdash; Курс &laquo;Структуры данных&raquo; &mdash; часть 4]
* [http://informatics.mccme.ru/course/view.php?id=18 informatics.mccme.ru &mdash; Курс &laquo;Структуры данных&raquo; &mdash; часть 4]
* [http://github.com/indy256/codelibrary/blob/master/java/src/TreapImplicitKey.java CodeLibrary &mdash; Treap with implicit key with interval modification]
* [[:Категория:Задачи: Декартово дерево по неявному ключу|Задачи: Декартово дерево по неявному ключу]]
* [http://github.com/ADJA/algos/blob/master/DataStructures/CartesianTreeImplicitKeys.cpp Algos &mdash; Cartesian tree using implicit keys]
* [[:Категория:Задачи: Дерево Корнеева|Задачи: Дерево Корнеева]]


[[Category:Балансирующиеся деревья]]
[[Category:Балансирующиеся деревья]]

Текущая версия от 15:09, 24 мая 2023

TLDR

Multimap с getMinValue

getMinValue(lKey, rKey)

class Treap {
    inline static minstd_rand gen;

    struct Node {
        int key, priority, value, minValue;
        Node *left = 0, *right = 0;
        Node(int key, int value) : key(key), priority(gen()), value(value), minValue(value) {}
    } *root = 0;

    int getMinValue(Node *n) const {
        return n ? n->minValue : 2e9;
    }

    void update(Node *n) {
        if (n)
            n->minValue = min({ getMinValue(n->left), n->value, getMinValue(n->right) });
    }

    Node *merge(Node *a, Node *b) {
        if (!a || !b)
            return a ? a : b;
        if (a->priority > b->priority) {
            a->right = merge(a->right, b);
            update(a);
            return a;
        } else {
            b->left = merge(a, b->left);
            update(b);
            return b;
        }
    }

    void split(Node *t, int key, Node *&a, Node *&b) {
        if (!t) {
            a = b = 0;
            return;
        }
        if (t->key < key) {
            split(t->right, key, t->right, b);
            a = t;
        } else {
            split(t->left, key, a, t->left);
            b = t;
        }
        update(a);
        update(b);
    }

public:
    void insert(int key, int value) {
        Node *a, *b;
        split(root, key, a, b);
        root = merge(a, merge(new Node(key, value), b));
    }

    void erase(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        root = merge(a, c);
    }

    void eraseOne(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        if (b)
            b = merge(b->left, b->right);
        root = merge(a, merge(b, c));
    }

    int getMinValue(int lKey, int rKey) {
        Node *a, *b, *c;
        split(root, lKey, a, b);
        split(b, rKey + 1, b, c);
        int res = getMinValue(b);
        root = merge(a, merge(b, c));
        return res;
    }
};

getMinValue(lIndex, rIndex)

class Treap {
    inline static minstd_rand gen;

    struct Node {
        int key, priority, size = 1, value, minValue;
        Node *left = 0, *right = 0;
        Node(int key, int value) : key(key), priority(gen()), value(value), minValue(value) {}
    } *root = 0;

    int getSize(Node *n) const {
        return n ? n->size : 0;
    }

    int getMinValue(Node *n) const {
        return n ? n->minValue : 2e9;
    }

    void update(Node *n) {
        if (n) {
            n->size = getSize(n->left) + 1 + getSize(n->right);
            n->minValue = min({ getMinValue(n->left), n->value, getMinValue(n->right) });
        }
    }

    Node *merge(Node *a, Node *b) {
        if (!a || !b)
            return a ? a : b;
        if (a->priority > b->priority) {
            a->right = merge(a->right, b);
            update(a);
            return a;
        } else {
            b->left = merge(a, b->left);
            update(b);
            return b;
        }
    }

    void split(Node *t, int key, Node *&a, Node *&b) {
        if (!t) {
            a = b = 0;
            return;
        }
        if (t->key < key) {
            split(t->right, key, t->right, b);
            a = t;
        } else {
            split(t->left, key, a, t->left);
            b = t;
        }
        update(a);
        update(b);
    }

    void splitByIndex(Node *t, int index, Node *&a, Node *&b) {
        if (!t) {
            a = b = 0;
            return;
        }
        int leftSize = getSize(t->left);
        if (leftSize < index) {
            splitByIndex(t->right, index - leftSize - 1, t->right, b);
            a = t;
        } else {
            splitByIndex(t->left, index, a, t->left);
            b = t;            
        }
        update(a);
        update(b);
    }

public:
    void insert(int key, int value) {
        Node *a, *b;
        split(root, key, a, b);
        root = merge(a, merge(new Node(key, value), b));
    }

    void erase(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        root = merge(a, c);
    }

    void eraseOne(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        if (b)
            b = merge(b->left, b->right);
        root = merge(a, merge(b, c));
    }

    int getMinValue(int lIndex, int rIndex) {
        Node *a, *b, *c;
        splitByIndex(root, lIndex, a, b);
        splitByIndex(b, rIndex - lIndex + 1, b, c);
        int res = getMinValue(b);
        root = merge(a, merge(b, c));
        return res;
    }
};

Multiset с indexOf(key), operator[], lessCount(key), greaterCount(key)

Одинаковые элементы хранятся в нескольких узлах

class Treap {
    inline static minstd_rand gen;

    struct Node {
        int key, priority, size = 1;
        Node *left = 0, *right = 0;
        Node(int key) : key(key), priority(gen()) {}
    } *root = 0;

    int getSize(Node *n) const {
        return n ? n->size : 0;
    }

    void update(Node *n) {
        if (n)
            n->size = getSize(n->left) + 1 + getSize(n->right);
    }

    Node *merge(Node *a, Node *b) {
        if (!a || !b)
            return a ? a : b;
        if (a->priority > b->priority) {
            a->right = merge(a->right, b);
            update(a);
            return a;
        } else {
            b->left = merge(a, b->left);
            update(b);
            return b;
        }
    }

    void split(Node *t, int key, Node *&a, Node *&b) {
        if (!t) {
            a = b = 0;
            return;
        }
        if (t->key < key) {
            split(t->right, key, t->right, b);
            a = t;
        } else {
            split(t->left, key, a, t->left);
            b = t;
        }
        update(a);
        update(b);
    }

    int indexOf(Node *n, int key) const {
        if (!n)
            return 0;
        else if (key < n->key)
            return indexOf(n->left, key);
        else if (n->key == key)
            return getSize(n->left);
        else
            return getSize(n->left) + 1 + indexOf(n->right, key);
    }

    int getByIndex(Node *n, int index) const {
        int leftSize = getSize(n->left);
        if (leftSize > index)
            return getByIndex(n->left, index);
        else if (leftSize == index)
            return n->key;
        else
            return getByIndex(n->right, index - leftSize - 1);
    }

public:
    int size() const {
        return getSize(root);
    }

    int indexOf(int key) const {
        return indexOf(root, key);
    }

    int operator[](int index) const {
        return getByIndex(root, index);
    }

    void insert(int key) {
        Node *a, *b;
        split(root, key, a, b);
        root = merge(a, merge(new Node(key), b));
    }

    void erase(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        root = merge(a, c);
    }

    void eraseOne(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        if (b)
            b = merge(b->left, b->right);
        root = merge(a, merge(b, c));
    }

    int lessCount(int key) {
        Node *a, *b;
        split(root, key, a, b);
        int res = getSize(a);
        root = merge(a, b);
        return res;
    }

    int lessEqualCount(int key) {
        Node *a, *b;
        split(root, key + 1, a, b);
        int res = getSize(a);
        root = merge(a, b);
        return res;
    }

    int greaterCount(int key) {
        Node *a, *b;
        split(root, key + 1, a, b);
        int res = getSize(b);
        root = merge(a, b);
        return res;
    }

    int greaterEqualCount(int key) {
        Node *a, *b;
        split(root, key, a, b);
        int res = getSize(b);
        root = merge(a, b);
        return res;
    }
};

Одинаковые элементы хранятся в одном узле

class Treap {
    inline static minstd_rand gen;

    struct Node {
        int key, priority, nodeSize = 1, subtreeSize = 1;
        Node *left = 0, *right = 0;
        Node(int key) : key(key), priority(gen()) {}
    } *root = 0;

    int getSubtreeSize(Node *n) const {
        return n ? n->subtreeSize : 0;
    }

    void update(Node *n) {
        if (n)
            n->subtreeSize = getSubtreeSize(n->left) + n->nodeSize + getSubtreeSize(n->right);
    }

    Node *merge(Node *a, Node *b) {
        if (!a || !b)
            return a ? a : b;
        if (a->priority > b->priority) {
            a->right = merge(a->right, b);
            update(a);
            return a;
        } else {
            b->left = merge(a, b->left);
            update(b);
            return b;
        }
    }

    void split(Node *t, int key, Node *&a, Node *&b) {
        if (!t) {
            a = b = 0;
            return;
        }
        if (t->key < key) {
            split(t->right, key, t->right, b);
            a = t;
        } else {
            split(t->left, key, a, t->left);
            b = t;
        }
        update(a);
        update(b);
    }

    int indexOf(Node *n, int key) const {
        if (!n)
            return 0;
        else if (key < n->key)
            return indexOf(n->left, key);
        else if (n->key == key)
            return getSubtreeSize(n->left);
        else
            return getSubtreeSize(n->left) + n->nodeSize + indexOf(n->right, key);
    }

    int getByIndex(Node *n, int index) const {
        int leftSize = getSubtreeSize(n->left);
        if (leftSize > index)
            return getByIndex(n->left, index);
        else if (leftSize + n->nodeSize >= index)
            return n->key;
        else
            return getByIndex(n->right, index - leftSize - n->nodeSize);
    }

public:
    int size() const {
        return getSubtreeSize(root);
    }

    int indexOf(int key) const {
        return indexOf(root, key);
    }

    int operator[](int index) const {
        return getByIndex(root, index);
    }

    void insert(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        if (b) {
            b->nodeSize++;
            b->subtreeSize++;
        } else {
            b = new Node(key);
        }
        root = merge(a, merge(b, c));
    }

    void erase(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        root = merge(a, c);
    }

    void eraseOne(int key) {
        Node *a, *b, *c;
        split(root, key, a, b);
        split(b, key + 1, b, c);
        if (b) {
            b->nodeSize--;
            b->subtreeSize--;
            if (!b->nodeSize)
                b = 0;
        }
        root = merge(a, merge(b, c));
    }

    int lessCount(int key) {
        Node *a, *b;
        split(root, key, a, b);
        int res = getSize(a);
        root = merge(a, b);
        return res;
    }

    int lessEqualCount(int key) {
        Node *a, *b;
        split(root, key + 1, a, b);
        int res = getSize(a);
        root = merge(a, b);
        return res;
    }

    int greaterCount(int key) {
        Node *a, *b;
        split(root, key + 1, a, b);
        int res = getSize(b);
        root = merge(a, b);
        return res;
    }

    int greaterEqualCount(int key) {
        Node *a, *b;
        split(root, key, a, b);
        int res = getSize(b);
        root = merge(a, b);
        return res;
    }
};

Set с find_by_order(index) и order_of_key(key) через __gnu_pbds

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using ordered_set = tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>;


Vector

getMinValue(lIndex, rIndex)

class ImplicitTreap {
    inline static minstd_rand gen;

    struct Node {
        int value, priority, size = 1, minValue;
        Node *left = 0, *right = 0;
        Node(int value) : value(value), priority(gen()), minValue(value) {}
    } *root = 0;

    int getSize(Node *n) {
        return n ? n->size : 0;
    }

    int getMinValue(Node *n) {
        return n ? n->minValue : 2e9;
    }

    void update(Node *n) {
        if (n) {
            n->size = getSize(n->left) + 1 + getSize(n->right);
            n->minValue = min({ getMinValue(n->left), n->value, getMinValue(n->right) });
        }
    }

    Node *merge(Node *a, Node *b) {
        if (!a || !b)
            return a ? a : b;
        if (a->priority > b->priority) {
            a->right = merge(a->right, b);
            update(a);
            return a;
        } else {
            b->left = merge(a, b->left);
            update(b);
            return b;
        }
    }

    void split(Node *t, int k, Node *&a, Node *&b) {
        if (!t) {
            a = b = 0;
            return;
        }
        if (getSize(t->left) < k) {
            split(t->right, k - getSize(t->left) - 1, t->right, b);
            a = t;
        } else {
            split(t->left, k, a, t->left);
            b = t;
        }
        update(a);
        update(b);
    }

public:
    void pushBack(int value) {
        root = merge(root, new Node(value));
    }

    void pushFront(int value) {
        root = merge(new Node(value), root);
    }

    void insertAfter(int index, int value) {
        Node *a, *b;
        split(root, index, a, b);
        root = merge(a, merge(new Node(value), b));
    }

    void erase(int index) {
        Node *a, *b, *c;
        split(root, index, a, b);
        split(b, 1, b, c);
        root = merge(a, c);
    }

    void erase(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        root = merge(a, c);
    }

    int operator[](int index) {
        Node *a, *b, *c;
        split(root, index, a, b);
        split(b, 1, b, c);
        int res = b->value;
        root = merge(a, merge(b, c));
        return res;
    }

    void moveToFront(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        root = merge(b, merge(a, c));
    }

    void moveToBack(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        root = merge(a, merge(c, b));
    }

    int getMinValue(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        int res = getMinValue(b);
        root = merge(a, merge(b, c));
        return res;
    }
};

reverse(lIndex, rIndex)

class ImplicitTreap {
    inline static minstd_rand gen;

    struct Node {
        int value, priority, size = 1, rev = 0;
        Node *left = 0, *right = 0;
        Node(int value) : value(value), priority(gen()) {}
    } *root = 0;

    int getSize(Node *n) {
        return n ? n->size : 0;
    }

    void push(Node *n) {
        if (n && n->rev) {
            swap(n->left, n->right);
            if (n->left)
                n->left->rev ^= 1;
            if (n->right)
                n->right->rev ^= 1;
            n->rev = 0;
        }
    }

    void update(Node *n) {
        if (n)
            n->size = getSize(n->left) + 1 + getSize(n->right);
    }

    Node *merge(Node *a, Node *b) {
        push(a);
        push(b);
        if (!a || !b)
            return a ? a : b;
        if (a->priority > b->priority) {
            a->right = merge(a->right, b);
            update(a);
            return a;
        } else {
            b->left = merge(a, b->left);
            update(b);
            return b;
        }
    }

    void split(Node *t, int k, Node *&a, Node *&b) {
        push(t);
        if (!t) {
            a = b = 0;
            return;
        }
        if (getSize(t->left) < k) {
            split(t->right, k - getSize(t->left) - 1, t->right, b);
            a = t;
        } else {
            split(t->left, k, a, t->left);
            b = t;
        }
        update(a);
        update(b);
    }

public:
    void pushBack(int value) {
        root = merge(root, new Node(value));
    }

    void pushFront(int value) {
        root = merge(new Node(value), root);
    }

    void insertAfter(int index, int value) {
        Node *a, *b;
        split(root, index, a, b);
        root = merge(a, merge(new Node(value), b));
    }

    void erase(int index) {
        Node *a, *b, *c;
        split(root, index, a, b);
        split(b, 1, b, c);
        root = merge(a, c);
    }

    void erase(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        root = merge(a, c);
    }

    int operator[](int index) {
        Node *a, *b, *c;
        split(root, index, a, b);
        split(b, 1, b, c);
        int res = b->value;
        root = merge(a, merge(b, c));
        return res;
    }

    void moveToFront(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        root = merge(b, merge(a, c));
    }

    void moveToBack(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        root = merge(a, merge(c, b));
    }

    void reverse(int lIndex, int rIndex) {
        Node *a, *b, *c;
        split(root, lIndex, a, b);
        split(b, rIndex - lIndex + 1, b, c);
        b->rev = 1;
        root = merge(a, merge(b, c));
    }
};

Ссылки

Теория:

Код:

Задачи: