Skip to the content.

:heavy_check_mark: 挿入/削除の可能な配列 (乱択二分探索木)
(binary-search-tree/rbst-array.hpp)

Depends on

Verified with

Code

#pragma once
#include "binary-search-tree/rbst-base.hpp"

template <typename T>
struct RBSTArrayNode {
  typename RBSTBase<RBSTArrayNode>::Ptr l, r;
  T key;
  int cnt;
  RBSTArrayNode(const T& t = T()) : l(), r(), key(t), cnt(1) {}
};

template <class T>
struct RBSTArray : RBSTBase<RBSTArrayNode<T>> {
  using Node = RBSTArrayNode<T>;
  using base = RBSTBase<Node>;
  using base::merge;
  using base::split;
  using typename base::Ptr;

  RBSTArray() = default;
  T get(Ptr& t, int k) {
    auto x = split(t, k);
    auto y = split(x.second, 1);
    T v = y.first->key;
    t = merge(x.first, merge(y.first, y.second));
    return v;
  }
  void set(Ptr& t, int k, T v) {
    auto x = split(t, k);
    auto y = split(x.second, 1);
    y.first->key = v;
    t = merge(x.first, merge(y.first, y.second));
  }

 protected:
  Ptr update(Ptr t) override {
    t->cnt = 1;
    if (t->l) t->cnt += t->l->cnt;
    if (t->r) t->cnt += t->r->cnt;
    return t;
  }
  void push(Ptr t) override {}
};

/**
 * @brief 挿入/削除の可能な配列 (乱択二分探索木)
 */
#line 2 "binary-search-tree/rbst-base.hpp"

template <class Node>
struct RBSTBase {
  using Ptr = Node*;
  template <typename... Args>
  inline Ptr my_new(Args... args) {
    return new Node(args...);
  }
  inline void my_del(Ptr t) { delete t; }
  inline Ptr make_tree() const { return nullptr; }

  int size(Ptr t) const { return count(t); }
  Ptr merge(Ptr l, Ptr r) {
    if (!l || !r) return l ? l : r;
    if (int((rng() * (l->cnt + r->cnt)) >> 32) < l->cnt) {
      push(l);
      l->r = merge(l->r, r);
      return update(l);
    } else {
      push(r);
      r->l = merge(l, r->l);
      return update(r);
    }
  }
  pair<Ptr, Ptr> split(Ptr t, int k) {
    if (!t) return {nullptr, nullptr};
    push(t);
    if (k <= count(t->l)) {
      auto s = split(t->l, k);
      t->l = s.second;
      return {s.first, update(t)};
    } else {
      auto s = split(t->r, k - count(t->l) - 1);
      t->r = s.first;
      return {update(t), s.second};
    }
  }
  Ptr build(int l, int r, const vector<decltype(Node::key)>& v) {
    if (l + 1 == r) return my_new(v[l]);
    int m = (l + r) >> 1;
    Ptr pm = my_new(v[m]);
    if (l < m) pm->l = build(l, m, v);
    if (m + 1 < r) pm->r = build(m + 1, r, v);
    return update(pm);
  }
  Ptr build(const vector<decltype(Node::key)>& v) {
    return build(0, (int)v.size(), v);
  }
  template <typename... Args>
  void insert(Ptr& t, int k, const Args&... args) {
    auto x = split(t, k);
    t = merge(merge(x.first, my_new(args...)), x.second);
  }
  void erase(Ptr& t, int k) {
    auto x = split(t, k);
    auto y = split(x.second, 1);
    my_del(y.first);
    t = merge(x.first, y.second);
  }

 protected:
  static uint64_t rng() {
    static uint64_t x_ = 123456789ull;
    return x_ ^= x_ << 7, x_ ^= x_ >> 9, x_ & 0xFFFFFFFFull;
  }
  inline int count(const Ptr t) const { return t ? t->cnt : 0; }
  virtual void push(Ptr) = 0;
  virtual Ptr update(Ptr) = 0;
};

/**
 * @brief Randomized Binary Search Tree (基底クラス)
 * @docs docs/binary-search-tree/rbst-base.md
 */
#line 3 "binary-search-tree/rbst-array.hpp"

template <typename T>
struct RBSTArrayNode {
  typename RBSTBase<RBSTArrayNode>::Ptr l, r;
  T key;
  int cnt;
  RBSTArrayNode(const T& t = T()) : l(), r(), key(t), cnt(1) {}
};

template <class T>
struct RBSTArray : RBSTBase<RBSTArrayNode<T>> {
  using Node = RBSTArrayNode<T>;
  using base = RBSTBase<Node>;
  using base::merge;
  using base::split;
  using typename base::Ptr;

  RBSTArray() = default;
  T get(Ptr& t, int k) {
    auto x = split(t, k);
    auto y = split(x.second, 1);
    T v = y.first->key;
    t = merge(x.first, merge(y.first, y.second));
    return v;
  }
  void set(Ptr& t, int k, T v) {
    auto x = split(t, k);
    auto y = split(x.second, 1);
    y.first->key = v;
    t = merge(x.first, merge(y.first, y.second));
  }

 protected:
  Ptr update(Ptr t) override {
    t->cnt = 1;
    if (t->l) t->cnt += t->l->cnt;
    if (t->r) t->cnt += t->r->cnt;
    return t;
  }
  void push(Ptr t) override {}
};

/**
 * @brief 挿入/削除の可能な配列 (乱択二分探索木)
 */
Back to top page