This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub kmyk/competitive-programming-library
/** * @note verified http://arc054.contest.atcoder.jp/submissions/1335245 * @note verified https://csacademy.com/contest/ceoi-2018-day-2/task/fibonacci-representations-small/ * @note you can implement this with unordered_map, but the constructor requires the size */ template <class Monoid> struct dynamic_segment_tree { // on monoid typedef Monoid monoid_type; typedef typename Monoid::value_type value_type; struct node_t { int left, right; // indices on pool value_type value; }; deque<node_t> pool; stack<int> bin; int root; // index ll width; // of the tree int size; // the number of leaves Monoid mon; dynamic_segment_tree(Monoid const & a_mon = Monoid()) : mon(a_mon) { node_t node = { -1, -1, mon.unit() }; pool.push_back(node); root = 0; width = 1; size = 1; } protected: int create_node(int parent, bool is_right) { // make a new node int i; if (bin.empty()) { i = pool.size(); node_t node = { -1, -1, mon.unit() }; pool.push_back(node); } else { i = bin.top(); bin.pop(); pool[i] = { -1, -1, mon.unit() }; } // link from the parent assert (parent != -1); int & ptr = is_right ? pool[parent].right : pool[parent].left; assert (ptr == -1); ptr = i; return i; } value_type get_value(int i) { return i == -1 ? mon.unit() : pool[i].value; } public: void point_set(ll i, value_type z) { assert (0 <= i); while (width <= i) { node_t node = { root, -1, pool[root].value }; root = pool.size(); pool.push_back(node); width *= 2; } point_set(root, -1, false, 0, width, i, z); } void point_set(int i, int parent, bool is_right, ll il, ll ir, ll j, value_type z) { if (il == j and ir == j + 1) { // 0-based if (i == -1) { i = create_node(parent, is_right); size += 1; } pool[i].value = z; } else if (ir <= j or j + 1 <= il) { // nop } else { if (i == -1) i = create_node(parent, is_right); point_set(pool[i].left, i, false, il, (il + ir) / 2, j, z); point_set(pool[i].right, i, true, (il + ir) / 2, ir, j, z); pool[i].value = mon.append(get_value(pool[i].left), get_value(pool[i].right)); } } void point_delete(ll i) { assert (0 <= i); if (width <= i) return; root = point_delete(root, -1, false, 0, width, i); } int point_delete(int i, int parent, bool is_right, ll il, ll ir, ll j) { if (i == -1) { return -1; } else if (il == j and ir == j + 1) { // 0-based bin.push(i); size -= 1; return -1; } else if (ir <= j or j + 1 <= il) { return i; } else { pool[i].left = point_delete(pool[i].left, i, false, il, (il + ir) / 2, j); pool[i].right = point_delete(pool[i].right, i, true, (il + ir) / 2, ir, j); if (pool[i].left == -1 and pool[i].right == -1 and i != root) { bin.push(i); size -= 1; return -1; } else { pool[i].value = mon.append(get_value(pool[i].left), get_value(pool[i].right)); return i; } } } value_type range_concat(ll l, ll r) { assert (0 <= l and l <= r); if (width <= l) return mon.unit(); return range_concat(root, 0, width, l, min(width, r)); } value_type range_concat(int i, ll il, ll ir, ll l, ll r) { if (i == -1) return mon.unit(); if (l <= il and ir <= r) { // 0-based return pool[i].value; } else if (ir <= l or r <= il) { return mon.unit(); } else { return mon.append( range_concat(pool[i].left, il, (il + ir) / 2, l, r), range_concat(pool[i].right, (il + ir) / 2, ir, l, r)); } } template <class Func> void traverse_leaves(Func func) { return traverse_leaves(root, 0, width, func); } template <class Func> void traverse_leaves(ll i, ll il, ll ir, Func func) { if (i == -1) return; if (ir - il == 1) { func(il, pool[i].value); } else { traverse_leaves(pool[i].left, il, (il + ir) / 2, func); traverse_leaves(pool[i].right, (il + ir) / 2, ir, func); } } };
#line 1 "old/dynamic-segment-tree.inc.cpp" /** * @note verified http://arc054.contest.atcoder.jp/submissions/1335245 * @note verified https://csacademy.com/contest/ceoi-2018-day-2/task/fibonacci-representations-small/ * @note you can implement this with unordered_map, but the constructor requires the size */ template <class Monoid> struct dynamic_segment_tree { // on monoid typedef Monoid monoid_type; typedef typename Monoid::value_type value_type; struct node_t { int left, right; // indices on pool value_type value; }; deque<node_t> pool; stack<int> bin; int root; // index ll width; // of the tree int size; // the number of leaves Monoid mon; dynamic_segment_tree(Monoid const & a_mon = Monoid()) : mon(a_mon) { node_t node = { -1, -1, mon.unit() }; pool.push_back(node); root = 0; width = 1; size = 1; } protected: int create_node(int parent, bool is_right) { // make a new node int i; if (bin.empty()) { i = pool.size(); node_t node = { -1, -1, mon.unit() }; pool.push_back(node); } else { i = bin.top(); bin.pop(); pool[i] = { -1, -1, mon.unit() }; } // link from the parent assert (parent != -1); int & ptr = is_right ? pool[parent].right : pool[parent].left; assert (ptr == -1); ptr = i; return i; } value_type get_value(int i) { return i == -1 ? mon.unit() : pool[i].value; } public: void point_set(ll i, value_type z) { assert (0 <= i); while (width <= i) { node_t node = { root, -1, pool[root].value }; root = pool.size(); pool.push_back(node); width *= 2; } point_set(root, -1, false, 0, width, i, z); } void point_set(int i, int parent, bool is_right, ll il, ll ir, ll j, value_type z) { if (il == j and ir == j + 1) { // 0-based if (i == -1) { i = create_node(parent, is_right); size += 1; } pool[i].value = z; } else if (ir <= j or j + 1 <= il) { // nop } else { if (i == -1) i = create_node(parent, is_right); point_set(pool[i].left, i, false, il, (il + ir) / 2, j, z); point_set(pool[i].right, i, true, (il + ir) / 2, ir, j, z); pool[i].value = mon.append(get_value(pool[i].left), get_value(pool[i].right)); } } void point_delete(ll i) { assert (0 <= i); if (width <= i) return; root = point_delete(root, -1, false, 0, width, i); } int point_delete(int i, int parent, bool is_right, ll il, ll ir, ll j) { if (i == -1) { return -1; } else if (il == j and ir == j + 1) { // 0-based bin.push(i); size -= 1; return -1; } else if (ir <= j or j + 1 <= il) { return i; } else { pool[i].left = point_delete(pool[i].left, i, false, il, (il + ir) / 2, j); pool[i].right = point_delete(pool[i].right, i, true, (il + ir) / 2, ir, j); if (pool[i].left == -1 and pool[i].right == -1 and i != root) { bin.push(i); size -= 1; return -1; } else { pool[i].value = mon.append(get_value(pool[i].left), get_value(pool[i].right)); return i; } } } value_type range_concat(ll l, ll r) { assert (0 <= l and l <= r); if (width <= l) return mon.unit(); return range_concat(root, 0, width, l, min(width, r)); } value_type range_concat(int i, ll il, ll ir, ll l, ll r) { if (i == -1) return mon.unit(); if (l <= il and ir <= r) { // 0-based return pool[i].value; } else if (ir <= l or r <= il) { return mon.unit(); } else { return mon.append( range_concat(pool[i].left, il, (il + ir) / 2, l, r), range_concat(pool[i].right, (il + ir) / 2, ir, l, r)); } } template <class Func> void traverse_leaves(Func func) { return traverse_leaves(root, 0, width, func); } template <class Func> void traverse_leaves(ll i, ll il, ll ir, Func func) { if (i == -1) return; if (ir - il == 1) { func(il, pool[i].value); } else { traverse_leaves(pool[i].left, il, (il + ir) / 2, func); traverse_leaves(pool[i].right, (il + ir) / 2, ir, func); } } };