/// Implicit Randomized Treap (Cartesian Tree) /// Simulate x (array index), simulate y (priority) /// Store value /// Maintain size of subtree /// total: sum of values in subtree /// Maintain reverse bit: a promise to reverse a segment /// Base Functions /// tSplitPos: split into first pos elements and the rest /// tMerge: merge two trees /// Array Interface /// tInsertPos: insert value at position pos /// tFindPos: return value at position pos /// Debugging /// tOutput: print bracket structure of tree /// Example Usage /// Add 20 elements to the middle /// Take array segments [0..10), [1, 11), ..., [9, 19) and reverse /// (disabled) Relax and output after every operation /// Relax and output after all operations /// Find values of all elements /// Split into two parts, check sizes #include using namespace std; auto gen = mt19937 (time (0)); using uniform = uniform_int_distribution ; struct Node; using PNode = Node *; int getSize (PNode t); using Num = long long; Num getTotal (PNode t); struct Node { Num value; Num total; int size; bool rev; PNode left; PNode right; void recalc () { size = 1 + getSize (left) + getSize (right); total = value + getTotal (left) + getTotal (right); } void relax () { if (rev) { swap (left, right); if (left != nullptr) left -> rev ^= true; if (right != nullptr) right -> rev ^= true; rev = false; } } Node (Num value_) { value = value_; total = value_; size = 1; rev = false; left = nullptr; right = nullptr; } ~Node () { if (left != nullptr) delete left; if (right != nullptr) delete right; } }; int getSize (PNode t) { return t == nullptr ? 0 : t -> size; } Num getTotal (PNode t) { return t == nullptr ? Num (0) : t -> total; } pair tSplitPos (PNode t, int pos) { if (t == nullptr) return {nullptr, nullptr}; t -> relax (); auto leftSize = getSize (t -> left); if (pos < leftSize + 1) { auto p = tSplitPos (t -> left, pos); t -> left = p.second; t -> recalc (); return {p.first, t}; } else { auto p = tSplitPos (t -> right, pos - leftSize - 1); t -> right = p.first; t -> recalc (); return {t, p.second}; } } PNode tMerge (PNode l, PNode r) { if (l == nullptr) return r; if (r == nullptr) return l; l -> relax (); r -> relax (); if (uniform (0, l -> size + r -> size - 1) (gen) < l -> size) { l -> right = tMerge (l -> right, r); l -> recalc (); return l; } else { r -> left = tMerge (l, r -> left); r -> recalc (); return r; } } PNode tInsertPos (PNode t, int pos, Num value) { auto v = new Node (value); auto p = tSplitPos (t, pos); auto half = tMerge (p.first, v); return tMerge (half, p.second); } void tOutput (PNode t, bool doEndl = true) { if (t != nullptr) { t -> relax (); cout << '('; tOutput (t -> left, false); cout << t -> value; // cout << t -> value << // '|' << t -> size << '"' << t -> total; tOutput (t -> right, false); cout << ')'; } if (doEndl) cout << '.' << endl; } Num tFindPos (PNode t, int pos) { if (t == nullptr) return Num (-1); t -> relax (); auto leftSize = getSize (t -> left); if (leftSize == pos) return t -> value; if (leftSize > pos) return tFindPos (t -> left, pos); else return tFindPos (t -> right, pos - leftSize - 1); } int main () { /* Node u; u.left; u.right; PNode v; (*v).left; (*v).right; v -> left; v -> right; */ int const limit = int (20); PNode root = nullptr; for (int x = 0; x < limit; x++) { root = tInsertPos (root, x, x); if (x < 20) tOutput (root); } for (int x = 0; x < limit / 2; x++) { auto p = tSplitPos (root, x + limit / 2); auto q = tSplitPos (p.first, x); q.second -> rev ^= true; p.first = tMerge (q.first, q.second); root = tMerge (p.first, p.second); // tOutput (root); } tOutput (root); for (int x = 0; x < limit; x++) { auto res = tFindPos (root, x); if (x < 5) cout << x << ' ' << res << endl; } { auto p = tSplitPos (root, limit - 5); cout << "sizes: " << getSize (p.first) << " " << getSize (p.second) << endl; root = tMerge (p.first, p.second); } return 0; }