From a4c035b6dc599febe142e20a97119bb181370d64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Ke=C3=9Fler?= Date: Sat, 16 Apr 2022 12:29:01 +0200 Subject: [PATCH] store covered length at each node separately --- segment_tree.cpp | 9 +++++---- segment_tree.h | 30 ++++++++++++++++++------------ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/segment_tree.cpp b/segment_tree.cpp index c0811d8..9c9e20e 100644 --- a/segment_tree.cpp +++ b/segment_tree.cpp @@ -6,7 +6,7 @@ #include "segment_tree.h" SegmentTree::SegmentTree(const std::vector &coords): - _covered_cross_section_length(0), _nodes() { + _nodes() { assert(!coords.empty()); @@ -15,7 +15,7 @@ SegmentTree::SegmentTree(const std::vector &coords): 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}); + _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 @@ -37,7 +37,7 @@ SegmentTree::SegmentTree(const std::vector &coords): void SegmentTree::add_interval(Interval interval, Index node_idx) { if (interval.left <= _nodes[node_idx].left_coord && _nodes[node_idx].right_coord <= interval.right) { - update_added(node_idx); + add_coverage(node_idx); } else { if(interval.left < left_child(node_idx).right_coord) { 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) { add_interval(interval, right_child_idx(node_idx)); } + update_covered_length(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) { - update_removed(node_idx); + remove_coverage(node_idx); } else { if(interval.left < left_child(node_idx).right_coord) { remove_interval(interval, left_child_idx(node_idx)); diff --git a/segment_tree.h b/segment_tree.h index 99aeb77..69ac54d 100644 --- a/segment_tree.h +++ b/segment_tree.h @@ -13,13 +13,13 @@ struct TreeNode { unsigned coverage; Coordinate left_coord; Coordinate right_coord; + Unit covered_length; inline Unit segment_length(); }; class SegmentTree { std::vector _nodes; - Unit _covered_cross_section_length; public: /** * @@ -36,8 +36,9 @@ private: inline static Index right_child_idx(Index node_idx); inline TreeNode& left_child(Index node_idx); inline TreeNode& right_child(Index node_idx); - inline void update_added(Index node_idx); - inline void update_removed(Index node_idx); + inline void add_coverage(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 remove_interval(Interval interval, Index node_idx); @@ -58,7 +59,7 @@ TreeNode& SegmentTree::right_child(Index node_idx) { } Unit SegmentTree::length_covered_intervals() { - return _covered_cross_section_length; + return _nodes.front().covered_length; } void SegmentTree::add_interval(Interval interval) { @@ -69,18 +70,14 @@ void SegmentTree::remove_interval(Interval interval) { remove_interval(interval, 0); } -void SegmentTree::update_added(Index node_idx) { +void SegmentTree::add_coverage(Index node_idx) { ++(_nodes[node_idx].coverage); - if(_nodes[node_idx].coverage == 1) { - _covered_cross_section_length += _nodes[node_idx].segment_length(); - } + update_covered_length(node_idx); } -void SegmentTree::update_removed(Index node_idx) { +void SegmentTree::remove_coverage(Index node_idx) { --(_nodes[node_idx].coverage); - if(_nodes[node_idx].coverage == 0) { - _covered_cross_section_length -= _nodes[node_idx].segment_length(); - } + update_covered_length(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; } +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() { return right_coord - left_coord;