#include #include using namespace std; mt19937 MyLittleRandom(100500); struct Node { int x; //int y; int sz; int sum; int add; int even; int pairs; int negapairs; Node* left; Node* right; Node(int cx) { x = cx; //y = MyLittleRandom(); sz = 1; sum = x; add = 0; even = (x % 2 ? 0 : 1); pairs = 0; negapairs = 0; left = nullptr; right = nullptr; } Node(Node* v) { x = v->x; sz = v->sz; sum = v->sum; add = v->add; even = v->even; pairs = v->pairs; negapairs = v->negapairs; left = v->left; right = v->right; } void push() { if (add) { if (left != nullptr) left->add += add; if (right != nullptr) right->add += add; x += add; add = 0; if (left != nullptr) left->update(); if (right != nullptr) right->update(); update(); // ? } } void update() { sz = 1; if (left != nullptr) sz += left->sz; if (right != nullptr) sz += right->sz; sum = x; if (left != nullptr) sum += left->sum; // includes left->add if (right != nullptr) sum += right->sum; sum += add * sz; even = (x % 2 ? 0 : 1); if (left != nullptr) even += left->even; if (right != nullptr) even += right->even; pairs = 0; if (left != nullptr) pairs += left->pairs; if (right != nullptr) pairs += right->pairs; if (left != nullptr && right != nullptr) { pairs += left->even * (right->sz - right->even); } if (x % 2) { if (left != nullptr) pairs += left->even; } else { if (right != nullptr) pairs += right->sz - right->even; } negapairs = 0; if (left != nullptr) negapairs += left->negapairs; if (right != nullptr) negapairs += right->negapairs; if (left != nullptr && right != nullptr) { negapairs += (left->sz - left->even) * right->sz; } if (x % 2) { if (left != nullptr) negapairs += left->sz - left->even; } else { if (right != nullptr) negapairs += right->even; } if (add % 2) { swap(pairs, negapairs); } } }; // ===== pair split(Node* root, int x, bool equal_value_to_right = true) { // < and >= if (root == nullptr) { return make_pair(nullptr, nullptr); } root = new Node(root); root->push(); if (root->x < x || (root->x == x && !equal_value_to_right)) { auto res = split(root->right, x, equal_value_to_right); root->right = res.first; root->update(); return make_pair(root, res.second); } else { auto res = split(root->left, x, equal_value_to_right); root->left = res.second; root->update(); return make_pair(res.first, root); } } pair split_k(Node* root, int k) { if (root == nullptr) { return make_pair(nullptr, nullptr); } root = new Node(root); root->push(); if (root->left != nullptr) { if (root->left->sz >= k) { auto res = split_k(root->left, k); root->left = res.second; root->update(); return make_pair(res.first, root); } else k -= root->left->sz; } if (k <= 0) { return make_pair(nullptr, root); } auto res = split_k(root->right, k - 1); root->right = res.first; root->update(); return make_pair(root, res.second); } Node* merge(Node* l, Node* r) { if (l == nullptr) return r; if (r == nullptr) return l; l = new Node(l); r = new Node(r); l->push(); r->push(); if (MyLittleRandom() * 1.0 / MyLittleRandom.max() < r->sz * 1.0 / (l->sz + r->sz)) { r->left = merge(l, r->left); r->update(); return r; } else { l->right = merge(l->right, r); l->update(); return l; } } // ===== Node* insert(Node* root, int x) { auto res = split(root, x); Node* x_tree = new Node(x); root = merge(x_tree, res.second); return merge(res.first, root); } Node* remove(Node* root, int x) { auto res = split(root, x); root = res.first; res = split(res.second, x, false); return merge(root, res.second); } Node* insert_k(Node* root, int x, int k) { auto res = split_k(root, k); Node* x_tree = new Node(x); root = merge(x_tree, res.second); return merge(res.first, root); } Node* remove_k(Node* root, int k) { auto res = split_k(root, k); root = res.first; res = split_k(res.second, 1); return merge(root, res.second); } Node* find(Node* root, int x) { if (root == nullptr) return nullptr; if (root->x == x) return root; if (root->x < x) { return find(root->right, x); } else { return find(root->left, x); } } Node* kth_element(Node* root, int k) { // 1-based if (root == nullptr) return nullptr; root->push(); if (root->left != nullptr) { if (root->left->sz >= k) { return kth_element(root->left, k); } else k -= root->left->sz; } if (k == 1) { return root; } return kth_element(root->right, k - 1); } pair segment_sum(Node* root, int l, int r) { // [l, r] auto res_1 = split_k(root, r); auto res_2 = split_k(res_1.first, l - 1); int ans = 0; if (res_2.second != nullptr) ans = res_2.second->sum; root = merge(res_2.first, res_2.second); root = merge(root, res_1.second); return make_pair(root, ans); } pair segment_pairs(Node* root, int l, int r) { // [l, r] auto res_1 = split_k(root, r); auto res_2 = split_k(res_1.first, l - 1); int ans = 0; if (res_2.second != nullptr) ans = res_2.second->pairs; root = merge(res_2.first, res_2.second); root = merge(root, res_1.second); return make_pair(root, ans); } Node* segment_add(Node* root, int l, int r, int a) { // [l, r] auto res_1 = split_k(root, r); auto res_2 = split_k(res_1.first, l - 1); if (res_2.second != nullptr) res_2.second->add += a; root = merge(res_2.first, res_2.second); root = merge(root, res_1.second); return root; } Node* segment_copy(Node* root, int l, int r) { // [l, r] auto res_1 = split_k(root, r); auto res_2 = split_k(res_1.first, l - 1); return merge(root, res_2.second); } // ===== int main() { Node* root = nullptr; vector root_history = { nullptr }; while (true) { char ch; cin >> ch; if (ch == '+') { int x, k; cin >> x >> k; root = insert_k(root, x, k); } if (ch == '-') { int k; cin >> k; root = remove_k(root, k); } /* if (ch == '?') { int x; cin >> x; auto res = find(root, x); if (res == nullptr) cout << "NO" << endl; else cout << "YES" << endl; } */ if (ch == 'k') { int k; cin >> k; auto res = kth_element(root, k); if (res == nullptr) cout << "NO" << endl; else cout << res->x << endl; } if (ch == 's') { int l, r; cin >> l >> r; auto res = segment_sum(root, l, r); root = res.first; cout << res.second << endl; } if (ch == 'p') { int l, r; cin >> l >> r; auto res = segment_pairs(root, l, r); root = res.first; cout << res.second << endl; } if (ch == 'a') { int l, r, a; cin >> l >> r >> a; root = segment_add(root, l, r, a); } if (ch == 'c') { int l, r; cin >> l >> r; root = segment_copy(root, l, r); } if (ch == '?') { int k, pos; cin >> k >> pos; auto res = kth_element(root_history[k], pos); if (res == nullptr) cout << "NO" << endl; else cout << res->x << endl; } root_history.push_back(root); cout << "# " << root_history.size() - 1 << endl; } return 0; }