// 4. Added size. Removed y. Size on [l..r). Sum on [l..r). #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 x; long long sum; int size; PNode left; PNode right; Node (Num x_) { x = x_; sum = x; size = 1; left = nullptr; right = nullptr; } void recalc () { size = 1; if (left != nullptr) size += left -> size; if (right != nullptr) size += right -> size; sum = x; 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; } /* void recalc (PNode t) { t -> size = 1; if (t -> left != nullptr) t -> size += t -> left -> size; if (t -> right != nullptr) t -> size += t -> right -> size; } */ pair tSplit (PNode t, Num x) { if (t == nullptr) return {nullptr, nullptr}; if (t -> x < x) { auto temp = tSplit (t -> right, x); t -> right = temp.first; t -> recalc (); // recalc (t); return {t, temp.second}; } else { auto temp = tSplit (t -> left, x); 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; // if (l -> y < r -> y) 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 x) { auto temp = tSplit (t, x); auto v = new Node (x); auto half = tMerge (temp.first, v); return tMerge (half, temp.second); } void tDeleteRecur (PNode t) { if (t == nullptr) return; tDeleteRecur (t -> left); tDeleteRecur (t -> right); delete t; } PNode tRemove (PNode t, Num x) { auto one = tSplit (t, x); auto two = tSplit (one.second, x + 1); // Num // one.first < x two.first == x two.second > x tDeleteRecur (two.first); return tMerge (one.first, two.second); } bool tFind (PNode t, Num x) { if (t == nullptr) return false; if (x < t -> x) return tFind (t -> left, x); if (t -> x < x) return tFind (t -> right, x); return true; } void tOutputRecur (PNode t) { if (t == nullptr) return; cout << "("; tOutputRecur (t -> left); cout << t -> x << "|" << t -> size; tOutputRecur (t -> right); cout << ")"; } void tOutput (PNode t) { #ifdef DEBUG if (t != nullptr) { cout << t -> x << " "; } tOutputRecur (t); cout << endl; #endif } tuple tCountBetween (PNode t, Num lo, Num hi) { // # [lo..hi) auto [a, b] = tSplit (t, lo); // a | b auto [c, d] = tSplit (b, hi); // a | c | d auto res = tSize (c); auto res2 = tSum (c); b = tMerge (c, d); return {res, res2, tMerge (a, b)}; } int main () { PNode root = nullptr; cout << "limit = " << limit << endl; for (int i = 0; i < limit; i++) { root = tInsert (root, (i * 3) % limit); tOutput (root); /* cout << (i * 1) % limit << "? " << tFind (root, (i * 1) % limit) << "\n"; */ } 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); } return 0; }