store covered length at each node separately
This commit is contained in:
parent
9bc33b22e9
commit
a4c035b6dc
2 changed files with 23 additions and 16 deletions
|
@ -6,7 +6,7 @@
|
||||||
#include "segment_tree.h"
|
#include "segment_tree.h"
|
||||||
|
|
||||||
SegmentTree::SegmentTree(const std::vector<RectCoord> &coords):
|
SegmentTree::SegmentTree(const std::vector<RectCoord> &coords):
|
||||||
_covered_cross_section_length(0), _nodes() {
|
_nodes() {
|
||||||
|
|
||||||
assert(!coords.empty());
|
assert(!coords.empty());
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ SegmentTree::SegmentTree(const std::vector<RectCoord> &coords):
|
||||||
size_t num_meta_nodes = std::bit_ceil(num_leaf_nodes) - 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});
|
_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
|
||||||
|
@ -37,7 +37,7 @@ SegmentTree::SegmentTree(const std::vector<RectCoord> &coords):
|
||||||
|
|
||||||
void SegmentTree::add_interval(Interval interval, Index node_idx) {
|
void SegmentTree::add_interval(Interval interval, Index node_idx) {
|
||||||
if (interval.left <= _nodes[node_idx].left_coord && _nodes[node_idx].right_coord <= interval.right) {
|
if (interval.left <= _nodes[node_idx].left_coord && _nodes[node_idx].right_coord <= interval.right) {
|
||||||
update_added(node_idx);
|
add_coverage(node_idx);
|
||||||
} else {
|
} else {
|
||||||
if(interval.left < left_child(node_idx).right_coord) {
|
if(interval.left < left_child(node_idx).right_coord) {
|
||||||
add_interval(interval, left_child_idx(node_idx));
|
add_interval(interval, left_child_idx(node_idx));
|
||||||
|
@ -45,12 +45,13 @@ void SegmentTree::add_interval(Interval interval, Index node_idx) {
|
||||||
if(right_child(node_idx).left_coord < interval.right) {
|
if(right_child(node_idx).left_coord < interval.right) {
|
||||||
add_interval(interval, right_child_idx(node_idx));
|
add_interval(interval, right_child_idx(node_idx));
|
||||||
}
|
}
|
||||||
|
update_covered_length(node_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SegmentTree::remove_interval(Interval interval, Index node_idx) {
|
void SegmentTree::remove_interval(Interval interval, Index node_idx) {
|
||||||
if (interval.left <= _nodes[node_idx].left_coord && _nodes[node_idx].right_coord <= interval.right) {
|
if (interval.left <= _nodes[node_idx].left_coord && _nodes[node_idx].right_coord <= interval.right) {
|
||||||
update_removed(node_idx);
|
remove_coverage(node_idx);
|
||||||
} else {
|
} else {
|
||||||
if(interval.left < left_child(node_idx).right_coord) {
|
if(interval.left < left_child(node_idx).right_coord) {
|
||||||
remove_interval(interval, left_child_idx(node_idx));
|
remove_interval(interval, left_child_idx(node_idx));
|
||||||
|
|
|
@ -13,13 +13,13 @@ struct TreeNode {
|
||||||
unsigned coverage;
|
unsigned coverage;
|
||||||
Coordinate left_coord;
|
Coordinate left_coord;
|
||||||
Coordinate right_coord;
|
Coordinate right_coord;
|
||||||
|
Unit covered_length;
|
||||||
inline Unit segment_length();
|
inline Unit segment_length();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class SegmentTree {
|
class SegmentTree {
|
||||||
std::vector<TreeNode> _nodes;
|
std::vector<TreeNode> _nodes;
|
||||||
Unit _covered_cross_section_length;
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -36,8 +36,9 @@ private:
|
||||||
inline static Index right_child_idx(Index node_idx);
|
inline static Index right_child_idx(Index node_idx);
|
||||||
inline TreeNode& left_child(Index node_idx);
|
inline TreeNode& left_child(Index node_idx);
|
||||||
inline TreeNode& right_child(Index node_idx);
|
inline TreeNode& right_child(Index node_idx);
|
||||||
inline void update_added(Index node_idx);
|
inline void add_coverage(Index node_idx);
|
||||||
inline void update_removed(Index node_idx);
|
inline void remove_coverage(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);
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ TreeNode& SegmentTree::right_child(Index node_idx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Unit SegmentTree::length_covered_intervals() {
|
Unit SegmentTree::length_covered_intervals() {
|
||||||
return _covered_cross_section_length;
|
return _nodes.front().covered_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SegmentTree::add_interval(Interval interval) {
|
void SegmentTree::add_interval(Interval interval) {
|
||||||
|
@ -69,18 +70,14 @@ void SegmentTree::remove_interval(Interval interval) {
|
||||||
remove_interval(interval, 0);
|
remove_interval(interval, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SegmentTree::update_added(Index node_idx) {
|
void SegmentTree::add_coverage(Index node_idx) {
|
||||||
++(_nodes[node_idx].coverage);
|
++(_nodes[node_idx].coverage);
|
||||||
if(_nodes[node_idx].coverage == 1) {
|
update_covered_length(node_idx);
|
||||||
_covered_cross_section_length += _nodes[node_idx].segment_length();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SegmentTree::update_removed(Index node_idx) {
|
void SegmentTree::remove_coverage(Index node_idx) {
|
||||||
--(_nodes[node_idx].coverage);
|
--(_nodes[node_idx].coverage);
|
||||||
if(_nodes[node_idx].coverage == 0) {
|
update_covered_length(node_idx);
|
||||||
_covered_cross_section_length -= _nodes[node_idx].segment_length();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Index SegmentTree::left_child_idx(Index node_idx) {
|
Index SegmentTree::left_child_idx(Index node_idx) {
|
||||||
|
@ -91,6 +88,15 @@ Index SegmentTree::right_child_idx(Index node_idx) {
|
||||||
return 2*node_idx + 2;
|
return 2*node_idx + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
_nodes[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;
|
||||||
|
|
Loading…
Reference in a new issue