Skip to content

Commit 0bc1c76

Browse files
committed
add rbst
1 parent 208393e commit 0bc1c76

File tree

5 files changed

+186
-0
lines changed

5 files changed

+186
-0
lines changed

binary-search-tree/rbst-array.hpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#pragma once
2+
#include "binary-search-tree/rbst-base.hpp"
3+
4+
template <typename T>
5+
struct RBSTArrayNode {
6+
typename RBSTBase<RBSTArrayNode>::Ptr l, r;
7+
T key;
8+
int cnt;
9+
RBSTArrayNode(const T& t = T()) : l(), r(), key(t), cnt(1) {}
10+
};
11+
12+
template <class T>
13+
struct RBSTArray : RBSTBase<RBSTArrayNode<T>> {
14+
using Node = RBSTArrayNode<T>;
15+
using base = RBSTBase<Node>;
16+
using base::merge;
17+
using base::split;
18+
using typename base::Ptr;
19+
20+
RBSTArray() = default;
21+
T get(Ptr& t, int k) {
22+
auto x = split(t, k);
23+
auto y = split(x.second, 1);
24+
T v = y.first->key;
25+
t = merge(x.first, merge(y.first, y.second));
26+
return v;
27+
}
28+
void set(Ptr& t, int k, T v) {
29+
auto x = split(t, k);
30+
auto y = split(x.second, 1);
31+
y.first->key = v;
32+
t = merge(x.first, merge(y.first, y.second));
33+
}
34+
35+
protected:
36+
Ptr update(Ptr t) override {
37+
t->cnt = 1;
38+
if (t->l) t->cnt += t->l->cnt;
39+
if (t->r) t->cnt += t->r->cnt;
40+
return t;
41+
}
42+
void push(Ptr t) override {}
43+
};
44+
45+
/**
46+
* @brief 挿入/削除の可能な配列 (乱択二分探索木)
47+
*/

binary-search-tree/rbst-base.hpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#pragma once
2+
3+
template <class Node>
4+
struct RBSTBase {
5+
using Ptr = Node*;
6+
template <typename... Args>
7+
inline Ptr my_new(Args... args) {
8+
return new Node(args...);
9+
}
10+
inline void my_del(Ptr t) { delete t; }
11+
inline Ptr make_tree() const { return nullptr; }
12+
13+
int size(Ptr t) const { return count(t); }
14+
Ptr merge(Ptr l, Ptr r) {
15+
if (!l || !r) return l ? l : r;
16+
if (int((rng() * (l->cnt + r->cnt)) >> 32) < l->cnt) {
17+
push(l);
18+
l->r = merge(l->r, r);
19+
return update(l);
20+
} else {
21+
push(r);
22+
r->l = merge(l, r->l);
23+
return update(r);
24+
}
25+
}
26+
pair<Ptr, Ptr> split(Ptr t, int k) {
27+
if (!t) return {nullptr, nullptr};
28+
push(t);
29+
if (k <= count(t->l)) {
30+
auto s = split(t->l, k);
31+
t->l = s.second;
32+
return {s.first, update(t)};
33+
} else {
34+
auto s = split(t->r, k - count(t->l) - 1);
35+
t->r = s.first;
36+
return {update(t), s.second};
37+
}
38+
}
39+
Ptr build(int l, int r, const vector<decltype(Node::key)>& v) {
40+
if (l + 1 == r) return my_new(v[l]);
41+
int m = (l + r) >> 1;
42+
Ptr pm = my_new(v[m]);
43+
if (l < m) pm->l = build(l, m, v);
44+
if (m + 1 < r) pm->r = build(m + 1, r, v);
45+
return update(pm);
46+
}
47+
Ptr build(const vector<decltype(Node::key)>& v) {
48+
return build(0, (int)v.size(), v);
49+
}
50+
template <typename... Args>
51+
void insert(Ptr& t, int k, const Args&... args) {
52+
auto x = split(t, k);
53+
t = merge(merge(x.first, my_new(args...)), x.second);
54+
}
55+
void erase(Ptr& t, int k) {
56+
auto x = split(t, k);
57+
auto y = split(x.second, 1);
58+
my_del(y.first);
59+
t = merge(x.first, y.second);
60+
}
61+
62+
protected:
63+
static uint64_t rng() {
64+
static uint64_t x_ = 123456789ull;
65+
return x_ ^= x_ << 7, x_ ^= x_ >> 9, x_ & 0xFFFFFFFFull;
66+
}
67+
inline int count(const Ptr t) const { return t ? t->cnt : 0; }
68+
virtual void push(Ptr) = 0;
69+
virtual Ptr update(Ptr) = 0;
70+
};
71+
72+
/**
73+
* @brief Randomized Binary Search Tree (基底クラス)
74+
* @docs docs/binary-search-tree/rbst-base.md
75+
*/
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
乱択二分探索木
2+
3+
実装は [https://nyaannyaan.github.io/library/rbst/rbst-base.hpp] を参考
4+
5+
split / merge を基にした実装.

util/xorshift.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#pragma once
2+
3+
namespace XORShift {
4+
unsigned int xor32() {
5+
static unsigned int x = 123456789u;
6+
x ^= x << 13, x ^= x >> 17, x ^= x << 5;
7+
return x;
8+
}
9+
unsigned long long xor64() {
10+
static unsigned long long x = 123456789ull;
11+
x ^= x << 13, x ^= x >> 7, x ^= x << 17;
12+
return x;
13+
}
14+
}; // namespace XORShift
15+
16+
/**
17+
* @brief XOR shift
18+
*/
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#define PROBLEM "https://judge.yosupo.jp/problem/aplusb"
2+
3+
#include "template/template.hpp"
4+
#include "binary-search-tree/rbst-array.hpp"
5+
#include "util/xorshift.hpp"
6+
7+
void test() {
8+
vector<int> a;
9+
RBSTArray<int> ar;
10+
auto t = ar.make_tree();
11+
12+
rep(loop, 0, 10000) {
13+
int type = XORShift::xor32() % 3;
14+
if (a.empty()) type = 0;
15+
if (type == 0) {
16+
int x = XORShift::xor32() % (a.size() + 1);
17+
int v = XORShift::xor32();
18+
a.insert(a.begin() + x, v);
19+
ar.insert(t, x, v);
20+
} else if (type == 1) {
21+
int x = XORShift::xor32() % a.size();
22+
int v = XORShift::xor32();
23+
a[x] = v;
24+
ar.set(t, x, v);
25+
} else {
26+
int x = XORShift::xor32() % a.size();
27+
a.erase(a.begin() + x);
28+
ar.erase(t, x);
29+
}
30+
assert(a.size() == ar.size(t));
31+
rep(i, 0, a.size()) assert(a[i] == ar.get(t, i));
32+
}
33+
}
34+
35+
int main() {
36+
test();
37+
38+
int a, b;
39+
in(a, b);
40+
out(a + b);
41+
}

0 commit comments

Comments
 (0)