/// Implicit Randomized Treap (Cartesian Tree) /// Simulate x (array index), simulate y (priority) /// Store value /// Maintain size of subtree /// total: sum of values in subtree /// largest: maximum of values in subtree /// 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 /// tAssignPos: assign value at position pos, assert it exists /// tRemovePos: remove value at position pos /// Debugging /// tOutput: print bracket structure of tree /// tOutput2: print vertical representation /// Example Usage /// Add 10^6 elements to the middle /// Cut middle part, check total and largest /// Reassign an element in the middle /// Cut middle part, check total and largest again /// Find values of all elements /// Remove half of elements from positions 0, then 1, then 2, etc /// (disabled) Remove other half of elements #include using namespace std; auto gen = mt19937 (time (0)); using uniform = uniform_int_distribution ; struct Node; using PNode = Node *; using Num = long long; int getSize (PNode t); Num getTotal (PNode t); Num getLargest (PNode t); struct Node { Num value; Num total; Num largest; int size; PNode left; PNode right; void recalc () { // size = 1 + getSize (this -> left) + getSize (this -> right); size = 1 + getSize (left) + getSize (right); total = value + getTotal (left) + getTotal (right); largest = max (value, max (getLargest (left), getLargest (right))); } Node (Num value_) { value = value_; total = value_; largest = value_; size = 1; 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;} Num getLargest (PNode t) {return (t == nullptr) ? Num (LLONG_MIN) : t -> largest;} pair tSplitPos (PNode t, int pos) { if (t == nullptr) return {nullptr, nullptr}; auto leftSize = getSize (t -> left); if (pos <= leftSize) { 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; if (uniform (0, l -> size + r -> size - 1) (gen) >= l -> size) { r -> left = tMerge (l, r -> left); r -> recalc (); return r; } else { l -> right = tMerge (l -> right, r); l -> recalc (); return l; } } 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) { cout << '('; tOutput (t -> left, false); // cout << t -> value << '|' << t -> size; cout << t -> value; tOutput (t -> right, false); cout << ')'; } if (doEndl) cout << '.' << endl; } void tOutput2 (PNode t, int depth = 1) { if (t != nullptr) { tOutput2 (t -> left, depth + 1); // cout << setw (depth) << ' ' << t -> x << endl; cout << setw (depth * 4) << ' ' << " value=" << t -> value << " total=" << t -> total << " largest=" << t -> largest << endl; tOutput2 (t -> right, depth + 1); } } Num tFindPos (PNode t, int pos) { if (t == nullptr) return Num (-1); 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); } PNode tAssignPos (PNode t, int pos, Num value) { if (t == nullptr) assert (false); auto leftSize = getSize (t -> left); if (leftSize == pos) { t -> value = value; t -> recalc (); return t; } if (leftSize > pos) { t -> left = tAssignPos (t -> left, pos, value); t -> recalc (); return t; } else { t -> right = tAssignPos (t -> right, pos - leftSize - 1, value); t -> recalc (); return t; } } PNode tRemovePos (PNode t, int pos) { if (t == nullptr) return t; auto leftSize = getSize (t -> left); if (leftSize == pos) { auto res = tMerge (t -> left, t -> right); t -> left = nullptr; t -> right = nullptr; delete t; return res; } if (leftSize > pos) { t -> left = tRemovePos (t -> left, pos); t -> recalc (); return t; } else { t -> right = tRemovePos (t -> right, pos - leftSize - 1); t -> recalc (); return t; } } int main () { /* Node u; u.x; u.y; u.left; u.right; PNode v; (*v).x; (*v).y; v -> x; v -> y; */ int const n = int (1E6); PNode root = nullptr; for (int x = 0; x < n; x++) { root = tInsertPos (root, x / 2, Num (x)); if (x < 0) {tOutput2 (root); cout << endl;} if (x < 10) tOutput (root); } { auto p = tSplitPos (root, 666666); auto q = tSplitPos (p.first, 333333); cout << q.second -> total << " " << q.second -> largest << endl; p.first = tMerge (q.first, q.second); root = tMerge (p.first, p.second); } { root = tAssignPos (root, 500000, 999998 + 2); } { auto p = tSplitPos (root, 666666); auto q = tSplitPos (p.first, 333333); cout << q.second -> total << " " << q.second -> largest << endl; p.first = tMerge (q.first, q.second); root = tMerge (p.first, p.second); } for (int x = 0; x < n; x++) { auto res = tFindPos (root, x); if (x < 10) {cout << x << ' ' << res << endl;} } for (int x = 0; x < n / 2; x++) { root = tRemovePos (root, x); if (getSize (root) <= 10) tOutput (root); } if (false) for (int x = 0; x < n / 2; x++) { root = tRemovePos (root, 0); if (getSize (root) <= 10) tOutput (root); } return 0; }