Skip to the content.

:warning: library/datastructure/binary_search_tree/ImplicitTreap.hpp

Depends on

Code

#pragma once
// https://xuzijian629.hatenablog.com/entry/2018/12/08/000452
#include "library/math/XorShift.hpp"
template <typename Lazy> class ImplicitTreap {
    using MX = typename Lazy::MX;
    using MF = typename Lazy::MF;
    using X = typename MX::value_type;
    using F = typename MF::value_type;
    struct Node {
        X val, prod;
        F lazy;
        int priority, cnt;
        bool rev;
        Node *l, *r;
        Node(X val, int priority = -1)
            : value(val), prod(MX::unit()), lazy(MF::unit()),
              priority(priority), cnt(1), rev(false), l(nullptr), r(nullptr) {
            if (priority < 0)
                priority = rnd();
        }
    };
    Node *root = nullptr;
    using Tree = Node *;

    int size(Tree t) { return t ? t->cnt : 0; }
    X prod(Tree t) { return t ? Lazy::mapping(t->lazy, t->prod) : MX::unit(); }

    void pushup(Tree t) {
        if (!t)
            return;
        t->cnt = 1 + size(t->l) + size(t->r);
        t->prod = MX::op(t->val, MX::op(prod(t->l), prod(t->r)));
    }
    void pushdown(Tree t) {
        if (!t)
            return;
        if (t->lazy != MF::unit()) {
            t->val = Lazy::mapping(t->val, t->lazy);
            if (t->l)
                MF::Rchop(t->l->lazy, t->lazy);
            if (t->r)
                MF::Rchop(t->r->lazy, t->lazy);
            t->lazy = MF::unit();
        }
        pushup(t);
    }

    void split(Tree t, int key, Tree &l, Tree &r) {
        if (!t) {
            l = r = nullptr;
            return;
        }
        pushdown(t);
        int implicit_key = size(t->l) + 1;
        if (key < implicit_key) {
            r = t;
            split(t->l, key, l, t->l);
        } else {
            l = t;
            split(t->r, key - implicit_key, t->r, r), l = t;
        }
        pushup(t);
    }

    void insert(Tree &t, int key, Tree item) {
        Tree t1, t2;
        split(t, key, t1, t2);
        merge(t1, t1, item);
        merge(t, t1, t2);
    }

    void merge(Tree &t, Tree l, Tree r) {
        pushdown(l);
        pushdown(r);
        if (!l or !r)
            t = l ? l : r;
        else if (l->priority > r->priority) {
            t = l;
            merge(l->r, l->r, r);
        } else {
            t = r;
            merge(r->l, l, r->l);
        }
        pushup(t);
    }

    void erase(Tree &t, int key) {
        Tree t1, t2, t3;
        split(t, key + 1, t1, t2);
        split(t1, key, t1, t3);
        merge(t, t1, t2);
    }

    void add(Tree t, int l, int r, int x) {
        Tree t1, t2, t3;
        split(t, l, t1, t2);
        split(t2, r - l, t2, t3);
        t2->lazy += x;
        t2->min += x;
        merge(t2, t2, t3);
        merge(t, t1, t2);
    }

    int findmin(Tree t, int l, int r) {
        Tree t1, t2, t3;
        split(t, l, t1, t2);
        split(t2, r - l, t2, t3);
        int ret = t2->min;
        merge(t2, t2, t3);
        merge(t, t1, t2);
        return ret;
    }

    // [l, r)の先頭がmになるように左シフトさせる。std::rotateと同じ仕様
    void rotate(Tree t, int l, int m, int r) {
        reverse(t, l, r);
        reverse(t, l, l + r - m);
        reverse(t, l + r - m, r);
    }

    void dump(Tree t) {
        if (!t)
            return;
        pushdown(t);
        dump(t->l);
        std::cout << t->value << " ";
        dump(t->r);
    }

  public:
    void insert(int pos, int x) {
        insert(root, pos, new Node(x, rnd.random()));
    }

    void add(int l, int r, int x) { add(root, l, r, x); }

    int findmin(int l, int r) { return findmin(root, l, r); }

    void erase(int pos) { erase(root, pos); }

    void reverse(int l, int r) { reverse(root, l, r); }

    void rotate(int l, int m, int r) { rotate(root, l, m, r); }

    void dump() {
        dump(root);
        std::cout << std::endl;
    }
};
#line 2 "library/datastructure/binary_search_tree/ImplicitTreap.hpp"
// https://xuzijian629.hatenablog.com/entry/2018/12/08/000452
#line 1 "library/math/XorShift.hpp"
class XorShift{
  uint64_t x;
public:
  XorShift(){
    mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
    x=rnd();
    for(int i=0;i<100;i++)(*this)();
  }
  uint64_t operator()(){
    x = x^(x<<7);
    return x = x^(x>>9);
  }
};
#line 4 "library/datastructure/binary_search_tree/ImplicitTreap.hpp"
template <typename Lazy> class ImplicitTreap {
    using MX = typename Lazy::MX;
    using MF = typename Lazy::MF;
    using X = typename MX::value_type;
    using F = typename MF::value_type;
    struct Node {
        X val, prod;
        F lazy;
        int priority, cnt;
        bool rev;
        Node *l, *r;
        Node(X val, int priority = -1)
            : value(val), prod(MX::unit()), lazy(MF::unit()),
              priority(priority), cnt(1), rev(false), l(nullptr), r(nullptr) {
            if (priority < 0)
                priority = rnd();
        }
    };
    Node *root = nullptr;
    using Tree = Node *;

    int size(Tree t) { return t ? t->cnt : 0; }
    X prod(Tree t) { return t ? Lazy::mapping(t->lazy, t->prod) : MX::unit(); }

    void pushup(Tree t) {
        if (!t)
            return;
        t->cnt = 1 + size(t->l) + size(t->r);
        t->prod = MX::op(t->val, MX::op(prod(t->l), prod(t->r)));
    }
    void pushdown(Tree t) {
        if (!t)
            return;
        if (t->lazy != MF::unit()) {
            t->val = Lazy::mapping(t->val, t->lazy);
            if (t->l)
                MF::Rchop(t->l->lazy, t->lazy);
            if (t->r)
                MF::Rchop(t->r->lazy, t->lazy);
            t->lazy = MF::unit();
        }
        pushup(t);
    }

    void split(Tree t, int key, Tree &l, Tree &r) {
        if (!t) {
            l = r = nullptr;
            return;
        }
        pushdown(t);
        int implicit_key = size(t->l) + 1;
        if (key < implicit_key) {
            r = t;
            split(t->l, key, l, t->l);
        } else {
            l = t;
            split(t->r, key - implicit_key, t->r, r), l = t;
        }
        pushup(t);
    }

    void insert(Tree &t, int key, Tree item) {
        Tree t1, t2;
        split(t, key, t1, t2);
        merge(t1, t1, item);
        merge(t, t1, t2);
    }

    void merge(Tree &t, Tree l, Tree r) {
        pushdown(l);
        pushdown(r);
        if (!l or !r)
            t = l ? l : r;
        else if (l->priority > r->priority) {
            t = l;
            merge(l->r, l->r, r);
        } else {
            t = r;
            merge(r->l, l, r->l);
        }
        pushup(t);
    }

    void erase(Tree &t, int key) {
        Tree t1, t2, t3;
        split(t, key + 1, t1, t2);
        split(t1, key, t1, t3);
        merge(t, t1, t2);
    }

    void add(Tree t, int l, int r, int x) {
        Tree t1, t2, t3;
        split(t, l, t1, t2);
        split(t2, r - l, t2, t3);
        t2->lazy += x;
        t2->min += x;
        merge(t2, t2, t3);
        merge(t, t1, t2);
    }

    int findmin(Tree t, int l, int r) {
        Tree t1, t2, t3;
        split(t, l, t1, t2);
        split(t2, r - l, t2, t3);
        int ret = t2->min;
        merge(t2, t2, t3);
        merge(t, t1, t2);
        return ret;
    }

    // [l, r)の先頭がmになるように左シフトさせる。std::rotateと同じ仕様
    void rotate(Tree t, int l, int m, int r) {
        reverse(t, l, r);
        reverse(t, l, l + r - m);
        reverse(t, l + r - m, r);
    }

    void dump(Tree t) {
        if (!t)
            return;
        pushdown(t);
        dump(t->l);
        std::cout << t->value << " ";
        dump(t->r);
    }

  public:
    void insert(int pos, int x) {
        insert(root, pos, new Node(x, rnd.random()));
    }

    void add(int l, int r, int x) { add(root, l, r, x); }

    int findmin(int l, int r) { return findmin(root, l, r); }

    void erase(int pos) { erase(root, pos); }

    void reverse(int l, int r) { reverse(root, l, r); }

    void rotate(int l, int m, int r) { rotate(root, l, m, r); }

    void dump() {
        dump(root);
        std::cout << std::endl;
    }
};
Back to top page