Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- #include <stdio.h>
- using namespace std;
- #define ll long long
- #define pll pair<ll, ll>
- #define vll vector<ll>
- #define pii pair<int, int>
- #define vpll vector<pll >
- #define vpii vector<pii >
- #define vii vector<int>
- #define f first
- #define s second
- #define mp make_pair
- #define pb push_back
- #define ld long double
- #define endl '\n'
- #define inf (ll)((ll)7e18)
- #define eps (ld)(1e-12)
- #define MOD (ll)((ll)1e9 + 7)
- #define MOD2 (ll)((ll)1e9 + 17)
- ostream& operator<<(ostream& os, vii& x)
- {
- for(int t : x)
- os << t << " ";
- return os;
- }
- ostream& operator<<(ostream& os, pii& x)
- {
- os << x.f << " " << x.s << " ";
- return os;
- }
- istream& operator>>(istream& is, pii& x)
- {
- is >> x.f >> x.s;
- return is;
- }
- mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
- std::uniform_int_distribution<int> distrib(1,100000000);
- vll p = {1, 239};
- vll p2 = {1, 396247};
- int globalCnt = 0;
- int globalCnt2 = 0;
- struct DescartesTree {
- DescartesTree() {
- root = nullptr;
- }
- struct Node {
- Node* left, *right;
- int key, y, md, size;
- int size2;
- Node(int key_) {
- left = nullptr;
- right = nullptr;
- size = 1;
- size2 = 1;
- y = rand(); //distrib(rng);
- key = key_;
- md = 0;
- }
- private:
- };
- Node* root;
- void update(Node* node) {
- if (node == nullptr) {
- return;
- }
- update2(node->left);
- update2(node->right);
- int size2 = 1;
- if (node->left != nullptr) {
- size2 += node->left->size2;
- }
- if (node->right != nullptr) {
- size2 += node->right->size2;
- }
- node->size2 = size2;
- int size = 1;
- if (node->left != nullptr) {
- size += node->left->size;
- }
- if (node->right != nullptr) {
- size += node->right->size;
- }
- node->size = size;
- if (size != size2) {
- assert(0);
- }
- if (node->left != nullptr) {
- node->left->md += node->md;
- }
- if (node->right != nullptr) {
- node->right ->md += node->md;
- }
- node->key += node->md;
- node->md = 0;
- }
- void update2(Node* node) {
- if (node == nullptr) {
- return;
- }
- update2(node->left);
- update2(node->right);
- int size = 1;
- if (node->left != nullptr) {
- size += node->left->size2;
- }
- if (node->right != nullptr) {
- size += node->right->size2;
- }
- node->size2 = size;
- }
- pair<Node*, Node*> split(int key, Node* node) {
- // cerr << "inside split" << endl;
- if (node == nullptr) {
- return {nullptr, nullptr};
- }
- update(node);
- if (node->key >= key) {
- pair<Node*, Node*> t = split(key, node->left);
- node->left = t.second;
- update(node);
- return {t.first, node};
- } else {
- pair<Node*, Node*> t = split(key, node->right);
- node->right = t.first;
- update(node);
- return {node, t.second};
- }
- }
- Node* merge(Node* left, Node* right) {
- // cerr << "inside merge" << endl;
- update(left);
- update(right);
- if (left == nullptr) {
- return right;
- }
- if (right == nullptr) {
- return left;
- }
- if (left->y < right->y) {
- left->right = merge(left->right, right);
- update(left);
- return left;
- } else {
- right->left = merge(left, right->left);
- update(right);
- return right;
- }
- }
- void insert(int key) {
- // cerr << "in insert" << endl;
- update(root);
- pair<Node*, Node*> sp1 = split(key, root);
- Node* newNode = new Node(key);
- sp1.f = merge(sp1.f, newNode);
- update(sp1.f);
- root = merge(sp1.f, sp1.s);
- update(root);
- }
- void erase(int key) {
- // cerr << "in erase" << endl;
- pair<Node*, Node*> sp1 = split(key, root);
- Node* cur = sp1.s;
- Node* prev = nullptr;
- vector<Node*> way;
- while (cur != nullptr && cur->left != nullptr) {
- way.pb(cur);
- update(cur);
- prev = cur;
- cur = cur->left;
- }
- update(cur);
- if (cur == nullptr || cur->key != key) {
- root = merge(sp1.f, sp1.s);
- return;
- }
- if (prev == nullptr) {
- prev = cur->right;
- update(prev);
- sp1.s = prev;
- } else {
- update(prev);
- prev->left = cur->right;
- update(prev->left);
- update(prev);
- }
- reverse(way.begin(), way.end());
- for (int i = 1; i < way.size(); ++i) {
- update(way[i]);
- }
- root = merge(sp1.f, sp1.s);
- }
- void addToSuff(Node* node, int x, int suffSize) {
- // cerr << "in addToSuff" << endl;
- update(node);
- if (suffSize <= 0 || node == nullptr) {
- return;
- }
- update(node->left); update(node->right); update(node);
- // cerr << "x " << x << " for node " << node->key << " node->size" << node->size << " suffSize " << suffSize << endl;
- // cerr << "children " << (node->left == nullptr ? 0 : node->left->size) << " right " << (node->right == nullptr ? 0 : node->right->size) << endl;
- if (globalCnt == 80) {
- if (x == 1) {
- cerr << "x " << x << " for node " << node->key << " node->size" << node->size << " suffSize " << suffSize << endl;
- }
- }
- if (node->size <= suffSize) {
- if (node->size < suffSize) {
- assert(0);
- }
- node->md += x;
- update(node);
- update(node->left); update(node->right);
- return;
- }
- if (node->right != nullptr) {
- update(node->right);
- addToSuff(node->right, x, min(suffSize, node->right->size));
- update(node);
- suffSize -= min(suffSize, node->right->size);
- }
- if (suffSize > 0) {
- update(node);
- node->key += x;
- update(node);
- update(node->left);
- addToSuff(node->left, x, suffSize - 1);
- update(node);
- }
- }
- int am(int key) {
- // cerr << "in am" << endl;
- update(root);
- pair<Node*, Node*> sp1 = split(key, root);
- pair<Node*, Node*> sp2 = split(key + 1, sp1.s);
- if (sp2.f == nullptr) {
- root = merge(sp2.f, sp2.s);
- update(root);
- root = merge(sp1.f, root);
- update(root);
- return 0;
- }
- update(sp2.f);
- int t = sp2.f->size;
- root = merge(sp2.f, sp2.s);
- update(root);
- root = merge(sp1.f, root);
- update(root);
- return t;
- }
- vii all_nodes;
- void cout_all_vals(Node* node) {
- update(node);
- if (node == nullptr) {
- return;
- }
- if (node->key < 0) {
- assert(0);
- }
- cout_all_vals(node->left);
- all_nodes.pb(node->key);
- cout_all_vals(node->right);
- }
- };
- void cout_all_good_nodes(vii& x) {
- for (auto el : x) {
- if (el != 0){
- cout << el << " ";
- }
- }
- }
- bool debugOut = 0;
- vii my_solve(int n, int m, vii a, vector<pair<char, int> > query) {
- DescartesTree tree1, tree2;
- int mx = 1000; //400005;
- for (int i = 0; i < mx; ++i) {
- tree1.insert(0);
- tree2.insert(0);
- }
- for (int i = 0; i < n; ++i) {
- int x = a[i];
- tree1.insert(x);
- tree2.addToSuff(tree2.root, 1, x);
- }
- for (int s = 0; s < m; ++s) {
- globalCnt2 = s;
- if (debugOut) {
- cout << "s " << s << endl;
- cout << "cerr_all_valls tree1 ";
- tree1.cout_all_vals(tree1.root); cout_all_good_nodes(tree1.all_nodes); cout << " end" << endl;
- cout << "cerr_all_valls tree2 ";
- tree2.cout_all_vals(tree2.root); cout_all_good_nodes(tree2.all_nodes); cout << " end" << endl;
- tree1.all_nodes.clear();
- tree2.all_nodes.clear();
- }
- char q;
- q = query[s].f;
- //cin >> q;
- if (q == 't') {
- swap(tree1, tree2);
- } else if (q == 'a') {
- int x;
- x = query[s].s;
- tree1.insert(x);
- tree2.addToSuff(tree2.root, 1, x);
- } else if (q == 'r') {
- int x;
- x = query[s].s;
- if (tree1.am(x) >= 1) {
- tree1.erase(x);
- tree2.addToSuff(tree2.root, -1, x);
- }
- } else {
- int x;
- x = query[s].s;
- cout << tree1.am(x) << endl;
- }
- }
- tree1.all_nodes = {};
- tree1.cout_all_vals(tree1.root);
- sort(tree1.all_nodes.begin(), tree1.all_nodes.end());
- vii res;
- bool wasNonZero = 0;
- for (auto el : tree1.all_nodes) {
- if (el != 0) {
- wasNonZero = 1;
- res.pb(el);
- } else if (wasNonZero) {
- assert(0);
- }
- }
- return res;
- }
- multiset<int> change(multiset<int> st) {
- vii sorted;
- while (st.size() > 0) {
- sorted.pb(*st.begin());
- st.erase(st.begin());
- }
- // cerr << "lal" << endl;
- multiset<int> answ;
- for (int i = 1; i <= (sorted.size() == 0 ? 0 : sorted.back()); ++i) {
- int cnt = 0;
- // cerr << "cnt " << cnt << endl;
- for (auto el : sorted) {
- if (el >= i) {
- ++cnt;
- }
- }
- answ.insert(cnt);
- }
- return answ;
- }
- vii getArr(multiset<int> st) {
- vii res;
- while (st.size() > 0) {
- res.pb(*st.begin());
- st.erase(st.begin());
- }
- return res;
- }
- int main() {
- ios_base::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- // freopen("movetofront.in", "r", stdin);
- // freopen("movetofront.out", "w", stdout);
- #ifdef LOCAL
- freopen("Input.txt", "r", stdin);
- freopen("Output.txt", "w", stdout);
- #endif
- srand(4);
- bool mode = 1;
- if (mode == 0) {
- int n, m;
- cin >> n >> m;
- vii x(n);
- for (int i = 0; i < n; ++i) {
- cin >> x[i];
- }
- vector<pair<char, int> > query;
- for (int i = 0; i < m; ++i) {
- char type;
- cin >> type;
- if (type == 't') {
- query.pb({type, 0});
- } else {
- int x;
- cin >> x;
- query.pb({type, x});
- }
- }
- vii j = my_solve(n, m, x, query);
- for (auto el : j) {
- cout << el << " ";
- }
- return 0;
- }
- if (mode == 1) {
- int n, m;
- n = 8, m = 7;
- vii x = {6, 4, 10, 2, 8, 6, 7, 1};
- vector<pair<char, int> > query;
- query = {{'r', 7}, {'t', 0}, {'a', 8}, {'t', 0}, {'t', 0}, {'r', 5}, {'t', 0}, {'r', 3}};
- debugOut = 1;
- vii j = my_solve(n, m, x, query);
- //debugOut = 0;
- for (int i = 0; i < 100; ++i) {
- globalCnt = i;
- vii t = my_solve(n, m, x, query);
- if (t != j) {
- cerr << "i " <<i << endl;
- cerr << "ub detected" << endl;
- cerr << 't' << t << endl;
- cerr << 'j' << j << endl;
- return 0;
- }
- }
- return 0;
- }
- for (int test = 0; test < 1000; ++test) {
- cerr << "test " << test << endl;
- int n = distrib(rng) % 10 + 1;
- int m = distrib(rng) % 10 + 1;
- vii x;
- multiset<int> st;
- for (int i = 0; i < n; ++i) {
- x.pb(distrib(rng) % 10 + 1);
- st.insert(x.back());
- }
- cerr << "here" << endl;
- vector<pair<char, int> > query;
- for (int i = 0; i < m; ++i) {
- int type = distrib(rng) % 4;
- if (type == 0) {
- int x = distrib(rng) % 10 + 1;
- query.push_back({'a', x});
- st.insert(x);
- } else if (type == 1) {
- int x = distrib(rng) % 10 + 1;
- query.push_back({'r', x});
- if (st.find(x) != st.end())
- st.erase(st.find(x));
- } else if (type >= 2) {
- query.push_back({'t', 0});
- st = change(st);
- }
- if (getArr(st) != my_solve(n, query.size(), x, query)) {
- cout << "failed operation " << type << endl;
- return 0;
- }
- }
- vii answ = getArr(st);
- reverse(answ.begin(), answ.end());
- vii my_answ = my_solve(n, m, x, query);
- reverse(answ.begin(), answ.end());
- if (my_answ != answ) {
- cout << "wrong" << endl;
- cout << "myAnsw " << my_answ << endl;
- cout << "theirAnsw " << answ << endl;
- cout << n << " " << m << endl;
- cout << x << endl;
- for (auto el : query) {
- if (el.f != 't') {
- cout << el.f << " " << el.s << endl;
- } else {
- cout << el.f << " " << endl;
- }
- }
- cout << endl;
- return 0;
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment