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

Материал из Олимпиадное программирование в УлГТУ
Перейти к навигации Перейти к поиску
Нет описания правки
Нет описания правки
 
(не показаны 3 промежуточные версии этого же участника)
Строка 1: Строка 1:
== TLDR ==
<youtube width="300" height="180">MLIbII4sBs0</youtube>
<youtube width="300" height="180">mkpeHhmmUPw</youtube>
== Multimap с getMinValue ==
== Multimap с getMinValue ==
{|width=100%
{|width=100%
Строка 13: Строка 17:
   
   
     int getMinValue(Node *n) const {
     int getMinValue(Node *n) const {
         return n ? n->minValue : 1e9;
         return n ? n->minValue : 2e9;
     }
     }
   
   
Строка 99: Строка 103:
   
   
     int getMinValue(Node *n) const {
     int getMinValue(Node *n) const {
         return n ? n->minValue : 1e9;
         return n ? n->minValue : 2e9;
     }
     }
   
   
Строка 491: Строка 495:




== Прочее ==
== Vector ==
 
{|width=100%
  struct TN {
|width=50%|
    int v, p, c, maxV;
'''getMinValue(lIndex, rIndex)'''
    TN *l, *r;
class ImplicitTreap {
    TN(int V) : v(V), p(rand()), c(1), maxV(V), l(0), r(0) {}
    inline static minstd_rand gen;
};
   
 
    struct Node {
  class ITreap {
        int value, priority, size = 1, minValue;
    TN *root;
        Node *left = 0, *right = 0;
     int getMaxV(TN *n) {
        Node(int value) : value(value), priority(gen()), minValue(value) {}
         return n ? n->maxV : -(1 << 30);
    } *root = 0;
   
     int getSize(Node *n) {
         return n ? n->size : 0;
     }
     }
     int getC(TN *n) {
         return n ? n->c : 0;
     int getMinValue(Node *n) {
         return n ? n->minValue : 2e9;
     }
     }
     void update(TN *n) {
         if (!n)
     void update(Node *n) {
             return;
         if (n) {
        n->c = 1 + getC(n->l) + getC(n->r);
             n->size = getSize(n->left) + 1 + getSize(n->right);
        n->maxV = max(n->v, max(getMaxV(n->l), getMaxV(n->r)));
            n->minValue = min({ getMinValue(n->left), n->value, getMinValue(n->right) });
        }
     }
     }
     TN *merge(TN *a, TN *b) {
     Node *merge(Node *a, Node *b) {
         if (!a || !b)
         if (!a || !b)
             return a ? a : b;
             return a ? a : b;
         if (a->p > b->p) {
         if (a->priority > b->priority) {
             a->r = merge(a->r, b);
             a->right = merge(a->right, b);
             update(a);
             update(a);
             return a;
             return a;
         } else {
         } else {
             b->l = merge(a, b->l);
             b->left = merge(a, b->left);
             update(b);
             update(b);
             return b;
             return b;
         }
         }
     }
     }
     void split(TN *t, int k, TN *&a, TN *&b) {
     void split(Node *t, int k, Node *&a, Node *&b) {
         if (!t) {
         if (!t) {
             a = b = 0;
             a = b = 0;
             return;
             return;
         }
         }
         if (getC(t->l) < k) {
         if (getSize(t->left) < k) {
             split(t->r, k - getC(t->l) - 1, t->r, b);
             split(t->right, k - getSize(t->left) - 1, t->right, b);
             a = t;            
             a = t;
         } else {
         } else {
             split(t->l, k, a, t->l);
             split(t->left, k, a, t->left);
             b = t;  
             b = t;
         }
         }
         update(a);
         update(a);
         update(b);
         update(b);
     }
     }
  public:
  public:
     ITreap() : root(0) {}
     void pushBack(int value) {
     int size() {
        root = merge(root, new Node(value));
         return getC(root);
    }
    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 insert(int pos, int v) {
         TN *a, *b;
     void moveToFront(int lIndex, int rIndex) {
         split(root, pos, a, b);
         Node *a, *b, *c;
         root = merge(a, merge(new TN(v), b));
         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 getMax(int l, int r) {
         TN *a, *b, *c;
     int getMinValue(int lIndex, int rIndex) {
         split(root, l, a, b);
         Node *a, *b, *c;
         split(b, r - l + 1, b, c);
         split(root, lIndex, a, b);
         int res = getMaxV(b);
         split(b, rIndex - lIndex + 1, b, c);
         int res = getMinValue(b);
         root = merge(a, merge(b, c));
         root = merge(a, merge(b, c));
         return res;
         return res;
     }
     }
  };
  };
 
|width=50%|
 
'''reverse(lIndex, rIndex)'''
 
class ImplicitTreap {
minstd_rand gen;
    inline static minstd_rand gen;
   
   
class ITreap {
     struct Node {
     struct Node {
         int value, priority, size = 1, rev = 0;
         int value, priority, size = 1, rev = 0;
         Node *l = 0, *r = 0;
         Node *left = 0, *right = 0;
         Node(int value) : value(value), priority(gen()) {}
         Node(int value) : value(value), priority(gen()) {}
     } *root = 0;
     } *root = 0;
Строка 578: Строка 631:
     void push(Node *n) {
     void push(Node *n) {
         if (n && n->rev) {
         if (n && n->rev) {
             swap(n->l, n->r);
             swap(n->left, n->right);
             if (n->l)
             if (n->left)
                 n->l->rev ^= 1;
                 n->left->rev ^= 1;
             if (n->r)
             if (n->right)
                 n->r->rev ^= 1;
                 n->right->rev ^= 1;
             n->rev = 0;
             n->rev = 0;
         }
         }
Строка 589: Строка 642:
     void update(Node *n) {
     void update(Node *n) {
         if (n)
         if (n)
             n->size = 1 + getSize(n->l) + getSize(n->r);
             n->size = getSize(n->left) + 1 + getSize(n->right);
     }
     }
   
   
Строка 598: Строка 651:
             return a ? a : b;
             return a ? a : b;
         if (a->priority > b->priority) {
         if (a->priority > b->priority) {
             a->r = merge(a->r, b);
             a->right = merge(a->right, b);
             update(a);
             update(a);
             return a;
             return a;
         } else {
         } else {
             b->l = merge(a, b->l);
             b->left = merge(a, b->left);
             update(b);
             update(b);
             return b;
             return b;
Строка 614: Строка 667:
             return;
             return;
         }
         }
         if (getSize(t->l) < k) {
         if (getSize(t->left) < k) {
             split(t->r, k - getSize(t->l) - 1, t->r, b);
             split(t->right, k - getSize(t->left) - 1, t->right, b);
             a = t;
             a = t;
         } else {
         } else {
             split(t->l, k, a, t->l);
             split(t->left, k, a, t->left);
             b = t;
             b = t;
         }
         }
Строка 625: Строка 678:
     }
     }
   
   
  public:  
  public:
     void pushBack(int value) {
     void pushBack(int value) {
         root = merge(root, new Node(value));
         root = merge(root, new Node(value));
     }
     }
   
   
     void reverse(int l, int r) {
     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;
         Node *a, *b, *c;
         split(root, l, a, b);
         split(root, index, a, b);
         split(b, r - l + 1, b, c);
         split(b, 1, b, c);
         b->rev = 1;
         root = merge(a, c);
         root = merge(a, merge(b, 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 get(int i) {
     int operator[](int index) {
         Node *a, *b, *c;
         Node *a, *b, *c;
         split(root, i, a, b);
         split(root, index, a, b);
         split(b, 1, b, c);
         split(b, 1, b, c);
         int res = b->value;
         int res = b->value;
         root = merge(a, merge(b, c));
         root = merge(a, merge(b, c));
         return res;
         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));
     }
     }
  };
  };
|}


== Ссылки ==
== Ссылки ==

Текущая версия от 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));
    }
};

Ссылки

Теория:

Код:

Задачи: