// // Created by maximilian on 16.04.22. // #include #include "geometry.h" #ifndef PROG_SEGMENT_TREE_H #define PROG_SEGMENT_TREE_H struct TreeNode { unsigned coverage; Coordinate left_coord; Coordinate right_coord; inline Unit segment_length(); }; class SegmentTree { std::vector _nodes; Unit _covered_cross_section_length; public: /** * * @param coords Sorted vector of coordinates */ SegmentTree(const std::vector& coords); inline Unit length_covered_intervals(); inline void add_interval(Interval interval); inline void remove_interval(Interval interval); private: inline static Index left_child_idx(Index node_idx); 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); void add_interval(Interval interval, Index node_idx); void remove_interval(Interval interval, Index node_idx); }; /***************************************************** * INLINE section ****************************************************/ TreeNode& SegmentTree::left_child(Index node_idx) { return _nodes[left_child_idx(node_idx)]; } TreeNode& SegmentTree::right_child(Index node_idx) { return _nodes[right_child_idx(node_idx)]; } Unit SegmentTree::length_covered_intervals() { return _covered_cross_section_length; } void SegmentTree::add_interval(Interval interval) { add_interval(interval, 0); } void SegmentTree::remove_interval(Interval interval) { remove_interval(interval, 0); } void SegmentTree::update_added(Index node_idx) { ++(_nodes[node_idx].coverage); if(_nodes[node_idx].coverage == 1) { _covered_cross_section_length += _nodes[node_idx].segment_length(); } } void SegmentTree::update_removed(Index node_idx) { --(_nodes[node_idx].coverage); if(_nodes[node_idx].coverage == 0) { _covered_cross_section_length -= _nodes[node_idx].segment_length(); } } Index SegmentTree::left_child_idx(Index node_idx) { return 2*node_idx + 1; } Index SegmentTree::right_child_idx(Index node_idx) { return 2*node_idx + 2; } Unit TreeNode::segment_length() { return right_coord - left_coord; } #endif //PROG_SEGMENT_TREE_H