// 5. Removed x. Added value. Split by left size. Reverse. Glue in other order. #include using namespace std; using Num = int; #ifdef DEBUG int const limit = 10; #else int const limit = 1000000; #endif mt19937 gen (1251521589); struct Node; typedef Node * PNode; struct Node { Num value; long long sum; int size; bool rev; PNode left; PNode right; Node (Num value_) { value = value_; sum = value; size = 1; rev = false; left = nullptr; right = nullptr; } void relax () { if (rev) { swap (left, right); if (left != nullptr) left -> rev ^= true; if (right != nullptr) right -> rev ^= true; rev = false; } } void recalc () { size = 1; if (left != nullptr) size += left -> size; if (right != nullptr) size += right -> size; sum = value; if (left != nullptr) sum += left -> sum; if (right != nullptr) sum += right -> sum; } }; int tSize (PNode t) { return (t == nullptr) ? 0 : t -> size; } long long tSum (PNode t) { return (t == nullptr) ? 0 : t -> sum; } pair tSplitPos (PNode t, int pos) { if (t == nullptr) return {nullptr, nullptr}; t -> relax (); auto leftSize = tSize (t -> left); if (leftSize + 1 <= pos) { auto temp = tSplitPos (t -> right, pos - leftSize - 1); t -> right = temp.first; t -> recalc (); return {t, temp.second}; } else { auto temp = tSplitPos (t -> left, pos); t -> left = temp.second; t -> recalc (); return {temp.first, t}; } } PNode tMerge (PNode l, PNode r) { if (l == nullptr) return r; if (r == nullptr) return l; l -> relax (); r -> relax (); if (uniform_int_distribution (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 tInsert (PNode t, Num value, int pos) { auto temp = tSplitPos (t, pos); auto v = new Node (value); auto half = tMerge (temp.first, v); return tMerge (half, temp.second); } void tOutputRecur (PNode t) { if (t == nullptr) return; t -> relax (); cout << "("; tOutputRecur (t -> left); cout << t -> value; // << "|" << t -> size; tOutputRecur (t -> right); cout << ")"; } void tOutput (PNode t) { #ifdef DEBUG if (t != nullptr) { cout << t -> value << " "; } tOutputRecur (t); cout << endl; #endif } tuple tCountBetween (PNode t, int lo, int hi) { // # [lo..hi) auto [a, b] = tSplitPos (t, lo); // a | b auto [c, d] = tSplitPos (b, hi - lo); // a | c | d auto res = tSize (c); auto res2 = tSum (c); b = tMerge (c, d); return {res, res2, tMerge (a, b)}; } PNode tReverseBetween (PNode t, int lo, int hi) { // # [lo..hi) auto [a, b] = tSplitPos (t, lo); // a | b auto [c, d] = tSplitPos (b, hi - lo); // a | c | d if (c != nullptr) { c -> rev ^= true; } // d | c | a /* b = tMerge (c, d); return tMerge (a, b); */ auto e = tMerge (d, c); return tMerge (e, a); } int main () { PNode root = nullptr; cout << "limit = " << limit << endl; for (int i = 0; i < limit; i++) { root = tInsert (root, i, i / 2); tOutput (root); } for (int i = 0; i < limit / 2; i++) { auto [res, res2, t] = tCountBetween (root, i, i * 2); cout << "[" << i << ".." << i * 2 << ") " << res << " " << res2 << endl; root = t; tOutput (root); } for (int i = 0; i < limit / 2; i++) { root = tReverseBetween (root, i, i + limit / 2); tOutput (root); } return 0; }