perm_tree.hpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <vector> | ||
| 4 | #include <array> | ||
| 5 | #include <cassert> | ||
| 6 | |||
| 7 | 11856 | class PermTree { | |
| 8 | // The tree is "left-associative": INCR/DECR nodes are structured as (1 INCR 2) INCR 3... | ||
| 9 | public: | ||
| 10 | enum class NodeType { | ||
| 11 | LEAF, | ||
| 12 | INCR, | ||
| 13 | DECR, | ||
| 14 | FULL, | ||
| 15 | PARTIAL, | ||
| 16 | }; | ||
| 17 | |||
| 18 | struct Node { | ||
| 19 | std::array<int, 2> c; | ||
| 20 | NodeType type; | ||
| 21 | int l, r, lo, hi; | ||
| 22 | }; | ||
| 23 | |||
| 24 | std::vector<Node> nodes; | ||
| 25 | int root = -1; | ||
| 26 | |||
| 27 | ✗ | PermTree() {} | |
| 28 |
8/8✓ Branch 2 → 3 taken 14452513 times.
✓ Branch 2 → 4 taken 3609497 times.
✓ Branch 3 → 4 taken 3672730 times.
✓ Branch 3 → 7 taken 10779783 times.
✓ Branch 8 → 9 taken 1748763 times.
✓ Branch 8 → 13 taken 9031020 times.
✓ Branch 9 → 10 taken 1527012 times.
✓ Branch 9 → 11 taken 221751 times.
|
18520645 | Node& operator [] (int idx) { return nodes[idx]; } |
| 29 | ✗ | const Node& operator [] (int idx) const { return nodes[idx]; } | |
| 30 | |||
| 31 |
2/2✓ Branch 982 → 51 taken 74725 times.
✓ Branch 982 → 983 taken 5913 times.
|
80638 | int size() const { return int(nodes.size()); } |
| 32 | |||
| 33 |
3/8PermTree::PermTree(std::__debug::vector<int, std::allocator<int> > const&):
✓ Branch 12 → 13 taken 5913 times.
✗ Branch 12 → 20 not taken.
✓ Branch 20 → 21 taken 5913 times.
PermTree::PermTree(std::vector<int, std::allocator<int> > const&):
✓ Branch 2 → 3 taken 30 times.
✗ Branch 2 → 6 not taken.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 7 not taken.
✗ Branch 9 → 10 not taken.
|
5973 | PermTree(const std::vector<int>& A) : nodes(A.empty() ? 0 : int(A.size())*2-1) { |
| 34 |
2/6PermTree::PermTree(std::__debug::vector<int, std::allocator<int> > const&):
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 38 taken 5913 times.
PermTree::PermTree(std::vector<int, std::allocator<int> > const&):
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 30 times.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 14 not taken.
|
5943 | if (A.empty()) { root = -1; return; } |
| 35 |
1/2✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 30 times.
|
5943 | int N = int(A.size()); |
| 36 |
2/3PermTree::PermTree(std::__debug::vector<int, std::allocator<int> > const&):
✓ Branch 46 → 47 taken 5913 times.
PermTree::PermTree(std::vector<int, std::allocator<int> > const&):
✓ Branch 11 → 12 taken 30 times.
✗ Branch 17 → 18 not taken.
|
5943 | std::vector<int> nxt_earlier(N); |
| 37 |
2/3PermTree::PermTree(std::__debug::vector<int, std::allocator<int> > const&):
✓ Branch 50 → 51 taken 5913 times.
PermTree::PermTree(std::vector<int, std::allocator<int> > const&):
✓ Branch 12 → 13 taken 30 times.
✗ Branch 21 → 22 not taken.
|
5943 | std::vector<int> prv_earlier(N); |
| 38 |
4/6PermTree::PermTree(std::__debug::vector<int, std::allocator<int> > const&):
✓ Branch 60 → 53 taken 40319 times.
✓ Branch 60 → 61 taken 5913 times.
PermTree::PermTree(std::vector<int, std::allocator<int> > const&):
✓ Branch 15 → 14 taken 9031020 times.
✓ Branch 15 → 16 taken 30 times.
✗ Branch 27 → 24 not taken.
✗ Branch 27 → 28 not taken.
|
9077282 | for (int i = 0; i < N; i++) { |
| 39 | 9071339 | nxt_earlier[i] = i+1; | |
| 40 | 9071339 | prv_earlier[i] = i-1; | |
| 41 | } | ||
| 42 |
4/6PermTree::PermTree(std::__debug::vector<int, std::allocator<int> > const&):
✓ Branch 83 → 62 taken 40319 times.
✓ Branch 83 → 84 taken 5913 times.
PermTree::PermTree(std::vector<int, std::allocator<int> > const&):
✓ Branch 22 → 17 taken 9031020 times.
✓ Branch 22 → 23 taken 30 times.
✗ Branch 39 → 29 not taken.
✗ Branch 39 → 40 not taken.
|
9077282 | for (int i = N-1; i >= 0; i--) { |
| 43 |
2/2✓ Branch 17 → 18 taken 8124136 times.
✓ Branch 17 → 19 taken 906884 times.
|
9071339 | int a = A[i]; |
| 44 |
2/2✓ Branch 17 → 18 taken 8124136 times.
✓ Branch 17 → 19 taken 906884 times.
|
9071339 | int p = prv_earlier[a]; |
| 45 | 9071339 | int n = nxt_earlier[a]; | |
| 46 |
4/6PermTree::PermTree(std::__debug::vector<int, std::allocator<int> > const&):
✓ Branch 72 → 73 taken 25148 times.
✓ Branch 72 → 77 taken 15171 times.
PermTree::PermTree(std::vector<int, std::allocator<int> > const&):
✓ Branch 17 → 18 taken 8124136 times.
✓ Branch 17 → 19 taken 906884 times.
✗ Branch 32 → 33 not taken.
✗ Branch 32 → 35 not taken.
|
9071339 | if (p != -1) nxt_earlier[p] = n; |
| 47 |
4/6PermTree::PermTree(std::__debug::vector<int, std::allocator<int> > const&):
✓ Branch 77 → 78 taken 25148 times.
✓ Branch 77 → 82 taken 15171 times.
PermTree::PermTree(std::vector<int, std::allocator<int> > const&):
✓ Branch 19 → 20 taken 7674358 times.
✓ Branch 19 → 21 taken 1356662 times.
✗ Branch 35 → 36 not taken.
✗ Branch 35 → 38 not taken.
|
9071339 | if (n != N) prv_earlier[n] = p; |
| 48 | } | ||
| 49 | |||
| 50 | 5943 | struct cnd_t { | |
| 51 | int left; | ||
| 52 | int lo; | ||
| 53 | int lo_gap; | ||
| 54 | int hi; | ||
| 55 | int hi_gap; | ||
| 56 | int node; | ||
| 57 | }; | ||
| 58 | |||
| 59 |
2/3PermTree::PermTree(std::__debug::vector<int, std::allocator<int> > const&):
✓ Branch 85 → 754 taken 5913 times.
PermTree::PermTree(std::vector<int, std::allocator<int> > const&):
✓ Branch 23 → 64 taken 30 times.
✗ Branch 40 → 41 not taken.
|
5943 | std::vector<cnd_t> stk; stk.reserve(N); |
| 60 | |||
| 61 |
4/6PermTree::PermTree(std::__debug::vector<int, std::allocator<int> > const&):
✓ Branch 754 → 86 taken 40319 times.
✓ Branch 754 → 755 taken 5913 times.
PermTree::PermTree(std::vector<int, std::allocator<int> > const&):
✓ Branch 64 → 24 taken 9031020 times.
✓ Branch 64 → 65 taken 30 times.
✗ Branch 189 → 42 not taken.
✗ Branch 189 → 190 not taken.
|
9077282 | for (int i = 0; i < N; i++) { |
| 62 | 9071339 | int a = A[i]; | |
| 63 | 16311637 | while (true) { | |
| 64 |
12/20PermTree::PermTree(std::__debug::vector<int, std::allocator<int> > const&):
✓ Branch 92 → 93 taken 45058 times.
✓ Branch 92 → 105 taken 5913 times.
✓ Branch 97 → 98 taken 39732 times.
✓ Branch 97 → 103 taken 5326 times.
✓ Branch 102 → 103 taken 5326 times.
✓ Branch 102 → 105 taken 34406 times.
PermTree::PermTree(std::vector<int, std::allocator<int> > const&):
✓ Branch 25 → 26 taken 12640487 times.
✓ Branch 25 → 29 taken 30 times.
✓ Branch 26 → 27 taken 10835184 times.
✓ Branch 26 → 28 taken 1805303 times.
✓ Branch 27 → 28 taken 1804194 times.
✓ Branch 27 → 29 taken 9030990 times.
✗ Branch 45 → 46 not taken.
✗ Branch 45 → 51 not taken.
✗ Branch 47 → 48 not taken.
✗ Branch 47 → 50 not taken.
✗ Branch 49 → 50 not taken.
✗ Branch 49 → 51 not taken.
✗ Branch 52 → 53 not taken.
✗ Branch 52 → 97 not taken.
|
12691488 | if (!stk.empty() && (a < stk.back().lo_gap || a > stk.back().hi_gap)) { |
| 65 | 3620149 | assert(stk.size() >= 2); | |
| 66 |
4/4✓ Branch 33 → 34 taken 3382346 times.
✓ Branch 33 → 35 taken 227151 times.
✓ Branch 36 → 37 taken 3382342 times.
✓ Branch 36 → 38 taken 227155 times.
|
3641453 | stk.end()[-2].lo = std::min(stk.end()[-2].lo, stk.back().lo); |
| 67 |
2/2✓ Branch 36 → 37 taken 3382342 times.
✓ Branch 36 → 38 taken 227155 times.
|
3641453 | stk.end()[-2].hi = std::max(stk.end()[-2].hi, stk.back().hi); |
| 68 | |||
| 69 | 3620149 | int n = 2 * stk.back().left - 1; | |
| 70 | 3641453 | nodes[n].c = {stk.end()[-2].node, stk.end()[-1].node}; | |
| 71 | 3620149 | nodes[n].type = NodeType::PARTIAL; | |
| 72 | 3630801 | nodes[n].l = stk.end()[-2].left; | |
| 73 | 3620149 | nodes[n].r = i-1; | |
| 74 | 3630801 | nodes[n].lo = stk.end()[-2].lo; | |
| 75 | 3630801 | nodes[n].hi = stk.end()[-2].hi; | |
| 76 | |||
| 77 | 3620149 | stk.pop_back(); | |
| 78 | |||
| 79 | 3620149 | stk.back().node = n; | |
| 80 | } else { | ||
| 81 | ✗ | break; | |
| 82 | } | ||
| 83 | 3620149 | } | |
| 84 | |||
| 85 |
1/2✓ Branch 29 → 40 taken 9031020 times.
✗ Branch 101 → 102 not taken.
|
9111658 | stk.push_back({i, a, prv_earlier[a]+1, a, nxt_earlier[a]-1, 2*i}); |
| 86 | 9071339 | nodes[2*i].type = NodeType::LEAF; | |
| 87 | 9071339 | nodes[2*i].c = {-1, -1}; | |
| 88 | 9071339 | nodes[2*i].l = nodes[2*i].r = i; | |
| 89 | 9071339 | nodes[2*i].lo = nodes[2*i].hi = a; | |
| 90 | |||
| 91 |
25/32PermTree::PermTree(std::__debug::vector<int, std::allocator<int> > const&):
✓ Branch 677 → 678 taken 46424 times.
✓ Branch 677 → 724 taken 17649 times.
✓ Branch 712 → 713 taken 23754 times.
✓ Branch 712 → 714 taken 22670 times.
✓ Branch 724 → 725 taken 46424 times.
✓ Branch 724 → 726 taken 17649 times.
✓ Branch 726 → 727 taken 46424 times.
✓ Branch 726 → 737 taken 17649 times.
✓ Branch 737 → 738 taken 46424 times.
✓ Branch 737 → 739 taken 17649 times.
✓ Branch 739 → 740 taken 46424 times.
✓ Branch 739 → 750 taken 17649 times.
✓ Branch 750 → 751 taken 46424 times.
✓ Branch 750 → 752 taken 17649 times.
✓ Branch 752 → 377 taken 23754 times.
✓ Branch 752 → 753 taken 40319 times.
PermTree::PermTree(std::vector<int, std::allocator<int> > const&):
✗ Branch 51 → 52 not taken.
✓ Branch 51 → 53 taken 14452513 times.
✓ Branch 53 → 54 taken 12215708 times.
✓ Branch 53 → 61 taken 2236805 times.
✓ Branch 54 → 55 taken 4875561 times.
✓ Branch 54 → 56 taken 7340147 times.
✓ Branch 57 → 58 taken 3055661 times.
✓ Branch 57 → 59 taken 9160047 times.
✓ Branch 60 → 61 taken 6794215 times.
✓ Branch 60 → 62 taken 5421493 times.
✗ Branch 170 → 171 not taken.
✗ Branch 170 → 186 not taken.
✗ Branch 184 → 185 not taken.
✗ Branch 184 → 186 not taken.
✗ Branch 187 → 109 not taken.
✗ Branch 187 → 188 not taken.
|
14655858 | while (stk.size() >= 2 && std::max(stk.back().hi, stk.end()[-2].hi) - std::min(stk.back().lo, stk.end()[-2].lo) == i - stk.end()[-2].left) { |
| 92 | // merge these two nodes into one | ||
| 93 |
4/4✓ Branch 42 → 43 taken 2063479 times.
✓ Branch 42 → 44 taken 3358014 times.
✓ Branch 62 → 41 taken 1841728 times.
✓ Branch 62 → 63 taken 3579765 times.
|
5492755 | stk.end()[-2].lo = std::min(stk.end()[-2].lo, stk.back().lo); |
| 94 |
4/4✓ Branch 42 → 43 taken 2063479 times.
✓ Branch 42 → 44 taken 3358014 times.
✓ Branch 45 → 46 taken 1841728 times.
✓ Branch 45 → 47 taken 3579765 times.
|
5492755 | stk.end()[-2].hi = std::max(stk.end()[-2].hi, stk.back().hi); |
| 95 | |||
| 96 |
2/2✓ Branch 45 → 46 taken 1841728 times.
✓ Branch 45 → 47 taken 3579765 times.
|
5445247 | int n = 2 * stk.back().left - 1; |
| 97 |
2/2✓ Branch 45 → 46 taken 1841728 times.
✓ Branch 45 → 47 taken 3579765 times.
|
5492755 | nodes[n].c = {stk.end()[-2].node, stk.end()[-1].node}; |
| 98 |
4/6PermTree::PermTree(std::__debug::vector<int, std::allocator<int> > const&):
✓ Branch 539 → 540 taken 10073 times.
✓ Branch 539 → 547 taken 13681 times.
PermTree::PermTree(std::vector<int, std::allocator<int> > const&):
✓ Branch 45 → 46 taken 1841728 times.
✓ Branch 45 → 47 taken 3579765 times.
✗ Branch 139 → 140 not taken.
✗ Branch 139 → 142 not taken.
|
5492755 | if (stk.end()[-2].lo == stk.end()[-1].lo) { |
| 99 | 1851801 | nodes[n].type = NodeType::DECR; | |
| 100 |
4/6PermTree::PermTree(std::__debug::vector<int, std::allocator<int> > const&):
✓ Branch 581 → 582 taken 10073 times.
✓ Branch 581 → 589 taken 3608 times.
PermTree::PermTree(std::vector<int, std::allocator<int> > const&):
✓ Branch 47 → 48 taken 3358014 times.
✓ Branch 47 → 49 taken 221751 times.
✗ Branch 148 → 149 not taken.
✗ Branch 148 → 151 not taken.
|
3620808 | } else if (stk.end()[-2].hi == stk.end()[-1].hi) { |
| 101 | 3368087 | nodes[n].type = NodeType::INCR; | |
| 102 | } else { | ||
| 103 | 225359 | nodes[n].type = NodeType::FULL; | |
| 104 | } | ||
| 105 | 5469001 | nodes[n].l = stk.end()[-2].left; | |
| 106 | 5445247 | nodes[n].r = i; | |
| 107 | 5469001 | nodes[n].lo = stk.end()[-2].lo; | |
| 108 | 5469001 | nodes[n].hi = stk.end()[-2].hi; | |
| 109 | |||
| 110 | 5445247 | stk.pop_back(); | |
| 111 | 5445247 | stk.back().node = n; | |
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | 5943 | assert(stk.size() == 1); | |
| 116 | 5943 | root = stk.back().node; | |
| 117 | 17769 | } | |
| 118 | }; | ||
| 119 |