cartesian_tree.hpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <vector> | ||
| 4 | #include <array> | ||
| 5 | |||
| 6 | #include "reverse_comparator.hpp" | ||
| 7 | |||
| 8 | 53 | class CartesianTree { | |
| 9 | public: | ||
| 10 | struct Node { | ||
| 11 | int l, m, r; // inclusive ranges | ||
| 12 | std::array<int, 2> c; | ||
| 13 | int p; | ||
| 14 | }; | ||
| 15 | std::vector<Node> nodes; | ||
| 16 | int root = -1; | ||
| 17 | |||
| 18 | ✗ | CartesianTree() {} | |
| 19 | |||
| 20 |
2/2✓ Branch 11 → 12 taken 9123447 times.
✓ Branch 11 → 15 taken 25 times.
|
9125228 | Node& operator [] (int idx) { return nodes[idx]; } |
| 21 | ✗ | const Node& operator [] (int idx) const { return nodes[idx]; } | |
| 22 | |||
| 23 |
4/4✓ Branch 539 → 69 taken 32 times.
✓ Branch 539 → 540 taken 7 times.
✓ Branch 1031 → 561 taken 32 times.
✓ Branch 1031 → 1032 taken 7 times.
|
78 | int size() const { return int(nodes.size()); } |
| 24 | |||
| 25 | private: | ||
| 26 | 39 | CartesianTree(std::vector<Node>&& nodes_, int root_) : nodes(std::move(nodes_)), root(root_) {} | |
| 27 | |||
| 28 | public: | ||
| 29 | |||
| 30 | // min-cartesian-tree, with earlier cells tiebroken earlier | ||
| 31 | template <typename T, typename Comp = std::less<T>> | ||
| 32 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 25 times.
|
39 | static CartesianTree build_min_tree(const std::vector<T>& v, Comp comp = Comp()) { |
| 33 |
2/2CartesianTree CartesianTree::build_min_tree<int, reverse_comparator_t<std::less<int> > >(std::__debug::vector<int, std::allocator<int> > const&, reverse_comparator_t<std::less<int> >):
✓ Branch 10 → 11 taken 7 times.
CartesianTree CartesianTree::build_min_tree<int, std::less<int> >(std::__debug::vector<int, std::allocator<int> > const&, std::less<int>):
✓ Branch 10 → 11 taken 7 times.
|
39 | std::vector<Node> nodes(v.size()*2+1); |
| 34 |
4/5CartesianTree CartesianTree::build_min_tree<int, reverse_comparator_t<std::less<int> > >(std::__debug::vector<int, std::allocator<int> > const&, reverse_comparator_t<std::less<int> >):
✓ Branch 19 → 129 taken 7 times.
CartesianTree CartesianTree::build_min_tree<int, std::less<int> >(std::__debug::vector<int, std::allocator<int> > const&, std::less<int>):
✓ Branch 19 → 127 taken 7 times.
CartesianTree CartesianTree::build_min_tree<int, std::less<int> >(std::vector<int, std::allocator<int> > const&, std::less<int>):
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 25 times.
✓ Branch 7 → 20 taken 25 times.
|
39 | std::vector<int> stk; stk.reserve(v.size()); |
| 35 | 9123575 | int root = -1; | |
| 36 |
4/8CartesianTree CartesianTree::build_min_tree<int, reverse_comparator_t<std::less<int> > >(std::__debug::vector<int, std::allocator<int> > const&, reverse_comparator_t<std::less<int> >):
✓ Branch 135 → 20 taken 39 times.
✗ Branch 135 → 136 not taken.
CartesianTree CartesianTree::build_min_tree<int, std::less<int> >(std::__debug::vector<int, std::allocator<int> > const&, std::less<int>):
✓ Branch 133 → 20 taken 39 times.
✗ Branch 133 → 134 not taken.
CartesianTree CartesianTree::build_min_tree<int, std::less<int> >(std::vector<int, std::allocator<int> > const&, std::less<int>):
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 9123497 times.
✓ Branch 22 → 8 taken 9123497 times.
✗ Branch 22 → 23 not taken.
|
9123575 | for (int i = 0; i <= int(v.size()); i++) { |
| 37 | 9123575 | int cur = 2*i; | |
| 38 | 9123575 | nodes[cur].l = i; | |
| 39 | 9123575 | nodes[cur].r = i-1; | |
| 40 | 9123575 | nodes[cur].m = i-1; | |
| 41 | 9123575 | nodes[cur].c = {-1, -1}; | |
| 42 |
18/18CartesianTree CartesianTree::build_min_tree<int, reverse_comparator_t<std::less<int> > >(std::__debug::vector<int, std::allocator<int> > const&, reverse_comparator_t<std::less<int> >):
✓ Branch 41 → 42 taken 56 times.
✓ Branch 41 → 93 taken 15 times.
✓ Branch 48 → 49 taken 42 times.
✓ Branch 48 → 66 taken 14 times.
✓ Branch 65 → 66 taken 18 times.
✓ Branch 65 → 93 taken 24 times.
CartesianTree CartesianTree::build_min_tree<int, std::less<int> >(std::__debug::vector<int, std::allocator<int> > const&, std::less<int>):
✓ Branch 41 → 42 taken 52 times.
✓ Branch 41 → 91 taken 19 times.
✓ Branch 48 → 49 taken 37 times.
✓ Branch 48 → 64 taken 15 times.
✓ Branch 63 → 64 taken 17 times.
✓ Branch 63 → 91 taken 20 times.
CartesianTree CartesianTree::build_min_tree<int, std::less<int> >(std::vector<int, std::allocator<int> > const&, std::less<int>):
✓ Branch 9 → 10 taken 15323746 times.
✓ Branch 9 → 15 taken 2923223 times.
✓ Branch 12 → 13 taken 12400521 times.
✓ Branch 12 → 14 taken 2923225 times.
✓ Branch 13 → 14 taken 6200247 times.
✓ Branch 13 → 15 taken 6200274 times.
|
33570899 | while (!stk.empty() && (i == int(v.size()) || comp(v[i], v[nodes[stk.back()].m]))) { |
| 43 | 9123536 | int nxt = stk.back(); stk.pop_back(); | |
| 44 | 9123536 | nodes[cur].p = nxt; | |
| 45 | 9123600 | nodes[nxt].c[1] = cur; | |
| 46 | 9123536 | nodes[nxt].r = nodes[cur].r; | |
| 47 | 9123536 | cur = nxt; | |
| 48 | } | ||
| 49 |
6/6CartesianTree CartesianTree::build_min_tree<int, reverse_comparator_t<std::less<int> > >(std::__debug::vector<int, std::allocator<int> > const&, reverse_comparator_t<std::less<int> >):
✓ Branch 99 → 100 taken 32 times.
✓ Branch 99 → 136 taken 7 times.
CartesianTree CartesianTree::build_min_tree<int, std::less<int> >(std::__debug::vector<int, std::allocator<int> > const&, std::less<int>):
✓ Branch 97 → 98 taken 32 times.
✓ Branch 97 → 134 taken 7 times.
CartesianTree CartesianTree::build_min_tree<int, std::less<int> >(std::vector<int, std::allocator<int> > const&, std::less<int>):
✓ Branch 17 → 18 taken 9123472 times.
✓ Branch 17 → 23 taken 25 times.
|
9123575 | if (i == int(v.size())) { |
| 50 | root = cur; | ||
| 51 | break; | ||
| 52 | } | ||
| 53 |
1/1✓ Branch 18 → 19 taken 9123472 times.
|
9123536 | nodes[2*i+1].l = nodes[cur].l; |
| 54 | 9123536 | nodes[2*i+1].m = i; | |
| 55 | 9123536 | nodes[cur].p = 2*i+1; | |
| 56 | 9123600 | nodes[2*i+1].c[0] = cur; | |
| 57 |
1/1✓ Branch 18 → 19 taken 9123472 times.
|
9123600 | stk.push_back(2*i+1); |
| 58 | } | ||
| 59 | 39 | nodes[root].p = -1; | |
| 60 | 53 | return {std::move(nodes), root}; | |
| 61 | 53 | } | |
| 62 | |||
| 63 | // max-cartesian-tree, with earlier cells tiebroken earlier | ||
| 64 | template <typename T, typename Comp = std::less<T>> | ||
| 65 | 7 | static CartesianTree build_max_tree(const std::vector<T>& v, Comp comp = Comp()) { | |
| 66 | 7 | return build_min_tree(v, reverse_comparator(comp)); | |
| 67 | } | ||
| 68 | }; | ||
| 69 |