add bottom case when updating covered lengths
This commit is contained in:
parent
3df8c5095d
commit
647d1da843
3 changed files with 24 additions and 14 deletions
6
main.cpp
6
main.cpp
|
@ -27,6 +27,12 @@ int main() {
|
||||||
add_rect(3,2,6,6);
|
add_rect(3,2,6,6);
|
||||||
check_area(28);
|
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;
|
std::cout << "All checks passed" << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -6,26 +6,24 @@
|
||||||
#include "segment_tree.h"
|
#include "segment_tree.h"
|
||||||
|
|
||||||
SegmentTree::SegmentTree(const std::vector<RectCoord> &coords):
|
SegmentTree::SegmentTree(const std::vector<RectCoord> &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());
|
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
|
// 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
|
// We initialize the tree from bottom up, keeping track of the index ranges
|
||||||
// and the length of the corresponding segment
|
// and the length of the corresponding segment
|
||||||
|
|
||||||
for(Index leaf_node_idx = 0 ; leaf_node_idx < num_leaf_nodes ; ++leaf_node_idx) {
|
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].left_coord = coords[leaf_node_idx].coord;
|
||||||
_nodes[leaf_node_idx + num_meta_nodes].right_coord = coords[leaf_node_idx +1].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
|
// 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].left_coord = left_child(node_idx).left_coord;
|
||||||
_nodes[node_idx].right_coord = right_child(node_idx).right_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);
|
update_covered_length(node_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ struct TreeNode {
|
||||||
|
|
||||||
|
|
||||||
class SegmentTree {
|
class SegmentTree {
|
||||||
|
size_t _num_leaf_nodes;
|
||||||
|
size_t _num_meta_nodes;
|
||||||
std::vector<TreeNode> _nodes;
|
std::vector<TreeNode> _nodes;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -41,6 +43,7 @@ private:
|
||||||
inline void update_covered_length(Index node_idx);
|
inline void update_covered_length(Index node_idx);
|
||||||
void add_interval(Interval interval, Index node_idx);
|
void add_interval(Interval interval, Index node_idx);
|
||||||
void remove_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) {
|
void SegmentTree::update_covered_length(Index node_idx) {
|
||||||
if (_nodes[node_idx].coverage > 0) {
|
if (_nodes[node_idx].coverage > 0) {
|
||||||
_nodes[node_idx].covered_length = _nodes[node_idx].segment_length();
|
_nodes[node_idx].covered_length = _nodes[node_idx].segment_length();
|
||||||
|
} else if (is_leaf(node_idx)) {
|
||||||
|
_nodes[node_idx].covered_length = 0;
|
||||||
} else {
|
} else {
|
||||||
_nodes[node_idx].covered_length = \
|
_nodes[node_idx].covered_length = \
|
||||||
left_child(node_idx).covered_length + right_child(node_idx).covered_length;
|
left_child(node_idx).covered_length + right_child(node_idx).covered_length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Unit TreeNode::segment_length() {
|
Unit TreeNode::segment_length() {
|
||||||
return right_coord - left_coord;
|
return right_coord - left_coord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SegmentTree::is_leaf(Index node_idx) {
|
||||||
|
return node_idx > _num_meta_nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif //PROG_SEGMENT_TREE_H
|
#endif //PROG_SEGMENT_TREE_H
|
||||||
|
|
Loading…
Reference in a new issue