diff --git a/main.cpp b/main.cpp index 3ace94d..d022bdd 100644 --- a/main.cpp +++ b/main.cpp @@ -27,6 +27,12 @@ int main() { add_rect(3,2,6,6); check_area(28); + add_rect(1,-2,8,4); + check_area(52); + + add_rect(2,2,7,3); + check_area(52); + std::cout << "All checks passed" << std::endl; return 0; } \ No newline at end of file diff --git a/segment_tree.cpp b/segment_tree.cpp index 55a374d..86f7c7f 100644 --- a/segment_tree.cpp +++ b/segment_tree.cpp @@ -6,26 +6,24 @@ #include "segment_tree.h" SegmentTree::SegmentTree(const std::vector &coords): - _nodes() { + _num_leaf_nodes(coords.size() -1), + // reserve nodes for a full binary tree with at least as many leaves as intervals + _num_meta_nodes(std::bit_ceil(_num_leaf_nodes) -1), + _nodes(2 * _num_meta_nodes + 1, {0, coords[_num_leaf_nodes].coord, coords[_num_leaf_nodes].coord, 0}) { assert(!coords.empty()); - // reserve nodes for a full binary tree with at least as many leaves as intervals - size_t num_leaf_nodes = coords.size() -1; - size_t num_meta_nodes = std::bit_ceil(num_leaf_nodes) - 1; - // Initialize all nodes with zero coverage and dummy interval - _nodes.resize(2 * num_meta_nodes + 1, {0, coords[num_leaf_nodes].coord, coords[num_leaf_nodes].coord, 0}); // We initialize the tree from bottom up, keeping track of the index ranges // and the length of the corresponding segment - for(Index leaf_node_idx = 0 ; leaf_node_idx < num_leaf_nodes ; ++leaf_node_idx) { - _nodes[leaf_node_idx + num_meta_nodes].left_coord = coords[leaf_node_idx].coord; - _nodes[leaf_node_idx + num_meta_nodes].right_coord = coords[leaf_node_idx +1].coord; + for(Index leaf_node_idx = 0 ; leaf_node_idx < _num_leaf_nodes ; ++leaf_node_idx) { + _nodes[leaf_node_idx + _num_meta_nodes].left_coord = coords[leaf_node_idx].coord; + _nodes[leaf_node_idx + _num_meta_nodes].right_coord = coords[leaf_node_idx + 1].coord; } // Note that there are remaining leafs that represent dummy ranges - for(Index node_idx = num_meta_nodes - 1; node_idx != -1 ; --node_idx) { + for(Index node_idx = _num_meta_nodes - 1; node_idx != -1 ; --node_idx) { _nodes[node_idx].left_coord = left_child(node_idx).left_coord; _nodes[node_idx].right_coord = right_child(node_idx).right_coord; } @@ -61,6 +59,4 @@ void SegmentTree::remove_interval(Interval interval, Index node_idx) { } update_covered_length(node_idx); } -} - - +} \ No newline at end of file diff --git a/segment_tree.h b/segment_tree.h index 69ac54d..6b929df 100644 --- a/segment_tree.h +++ b/segment_tree.h @@ -19,6 +19,8 @@ struct TreeNode { class SegmentTree { + size_t _num_leaf_nodes; + size_t _num_meta_nodes; std::vector _nodes; public: /** @@ -41,6 +43,7 @@ private: inline void update_covered_length(Index node_idx); void add_interval(Interval interval, Index node_idx); void remove_interval(Interval interval, Index node_idx); + inline bool is_leaf(Index node_idx); }; @@ -91,16 +94,21 @@ Index SegmentTree::right_child_idx(Index node_idx) { void SegmentTree::update_covered_length(Index node_idx) { if (_nodes[node_idx].coverage > 0) { _nodes[node_idx].covered_length = _nodes[node_idx].segment_length(); + } else if (is_leaf(node_idx)) { + _nodes[node_idx].covered_length = 0; } else { _nodes[node_idx].covered_length = \ left_child(node_idx).covered_length + right_child(node_idx).covered_length; } } - Unit TreeNode::segment_length() { return right_coord - left_coord; } +bool SegmentTree::is_leaf(Index node_idx) { + return node_idx > _num_meta_nodes; +} + #endif //PROG_SEGMENT_TREE_H