Skip to content

Commit ff3d189

Browse files
authored
Merge pull request #5 from mdonaka/perf/dynamic-segment-tree-pointer-based
perf: Optimize DynamicSegmentTree performance
2 parents a6c8c03 + a140f29 commit ff3d189

File tree

3 files changed

+57
-51
lines changed

3 files changed

+57
-51
lines changed

.clangd

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
InlayHints:
2+
Enabled: No
3+
ParameterNames: No
4+
DeducedTypes: No
5+
Designators: No

.verify-helper/timestamps.remote.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
"Test/DataStructure/DisjointSparseTable_xor.test.cpp": "2024-12-27 16:29:20 +0900",
1717
"Test/DataStructure/DynamicLiChaoTree.test.cpp": "2024-12-27 17:07:26 +0900",
1818
"Test/DataStructure/DynamicLiChaoTree_segment.test.cpp": "2024-12-27 17:07:26 +0900",
19-
"Test/DataStructure/DynamicSegmentTree.test.cpp": "2024-12-27 16:29:20 +0900",
20-
"Test/DataStructure/DynamicSegmentTree_RMQ.test.cpp": "2024-12-27 16:29:20 +0900",
21-
"Test/DataStructure/DynamicSegmentTree_RSQ.test.cpp": "2024-12-27 16:29:20 +0900",
19+
"Test/DataStructure/DynamicSegmentTree.test.cpp": "2025-12-20 16:12:20 +0000",
20+
"Test/DataStructure/DynamicSegmentTree_RMQ.test.cpp": "2025-12-20 16:12:20 +0000",
21+
"Test/DataStructure/DynamicSegmentTree_RSQ.test.cpp": "2025-12-20 16:12:20 +0000",
2222
"Test/DataStructure/LazySegmentTree_RAQRMQ.test.cpp": "2025-01-24 16:43:48 +0900",
2323
"Test/DataStructure/LazySegmentTree_RAQRSQ.test.cpp": "2025-01-24 16:43:48 +0900",
2424
"Test/DataStructure/LazySegmentTree_RUQRMQ.test.cpp": "2025-01-24 16:43:48 +0900",
Lines changed: 49 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
#pragma once
22

3-
#include <deque>
3+
#include <memory>
44
#include <ostream>
5-
#include <unordered_map>
65
#include <utility>
76
#include <vector>
87

@@ -12,72 +11,74 @@ namespace mtd {
1211
template <monoid Monoid, int size = static_cast<int>(1e9 + 1)>
1312
class DynamicSegmentTree {
1413
private:
15-
std::unordered_map<int, Monoid> m_node;
1614
using S = decltype(Monoid().m_val);
1715

18-
constexpr auto _get(int i) const {
19-
return (m_node.find(i) == m_node.end()) ? Monoid() : m_node.at(i);
20-
}
16+
struct Node {
17+
Monoid val;
18+
std::unique_ptr<Node> left;
19+
std::unique_ptr<Node> right;
20+
Node() : val(Monoid()), left(nullptr), right(nullptr) {}
21+
explicit Node(const Monoid& v) : val(v), left(nullptr), right(nullptr) {}
22+
};
23+
24+
std::unique_ptr<Node> m_root;
2125

2226
template <class Lambda>
23-
constexpr auto _update_op(int itr, Monoid&& val, const Lambda& op) {
24-
int i = itr + size - 1;
25-
m_node[i] = op(_get(i), std::forward<decltype(val)>(val));
26-
while (i) {
27-
i = (i - 1) >> 1;
28-
m_node[i] = _get((i << 1) | 1).binaryOperation(_get((i + 1) << 1LL));
27+
constexpr void _update_op(std::unique_ptr<Node>& node, int l, int r, int pos,
28+
Monoid&& val, const Lambda& op) {
29+
if (!node) node = std::make_unique<Node>();
30+
if (r - l == 1) {
31+
node->val = op(node->val, std::forward<Monoid>(val));
32+
return;
2933
}
30-
}
31-
32-
constexpr auto _query(int _l, int _r) const {
33-
_l = std::max(_l, 0);
34-
_r = std::min(_r, size - 1);
35-
auto l = _l + size;
36-
int r = _r + size;
37-
auto lm = Monoid();
38-
auto rm = Monoid();
39-
while (l <= r) {
40-
if (l & 1) {
41-
lm = lm.binaryOperation(_get(l - 1));
42-
++l;
43-
}
44-
if (!(r & 1)) {
45-
rm = _get(r - 1).binaryOperation(rm);
46-
--r;
47-
}
48-
l >>= 1, r >>= 1;
34+
int mid = l + (r - l) / 2;
35+
if (pos < mid) {
36+
_update_op(node->left, l, mid, pos, std::forward<Monoid>(val), op);
37+
} else {
38+
_update_op(node->right, mid, r, pos, std::forward<Monoid>(val), op);
4939
}
50-
return lm.binaryOperation(rm);
40+
Monoid left_val = node->left ? node->left->val : Monoid();
41+
Monoid right_val = node->right ? node->right->val : Monoid();
42+
node->val = left_val.binaryOperation(right_val);
5143
}
5244

53-
constexpr auto _construct(const std::vector<S>& vec) {
54-
for (unsigned int i = 0; i < vec.size(); ++i) {
55-
m_node[i + size - 1] = Monoid(vec[i]);
56-
}
57-
for (int i = size - 2; i >= 0; --i) {
58-
m_node[i] = _get((i << 1) | 1).binaryOperation(_get((i + 1) << 1));
59-
}
45+
constexpr Monoid _query(const std::unique_ptr<Node>& node, int l, int r,
46+
int ql, int qr) const {
47+
if (!node || r <= ql || qr <= l) return Monoid();
48+
if (ql <= l && r <= qr) return node->val;
49+
int mid = l + (r - l) / 2;
50+
return _query(node->left, l, mid, ql, qr)
51+
.binaryOperation(_query(node->right, mid, r, ql, qr));
6052
}
6153

6254
public:
63-
constexpr DynamicSegmentTree() {}
55+
constexpr DynamicSegmentTree() : m_root(nullptr) {}
6456

6557
template <class Lambda>
66-
constexpr auto update_op(int itr, Monoid&& val, const Lambda& op) {
67-
return _update_op(itr, std::forward<Monoid>(val), op);
58+
constexpr auto update_op(int pos, Monoid&& val, const Lambda& op) {
59+
return _update_op(m_root, 0, size, pos, std::forward<Monoid>(val), op);
6860
}
69-
constexpr auto update(int itr, Monoid&& val) {
70-
return update_op(itr, std::forward<Monoid>(val),
61+
62+
constexpr auto update(int pos, Monoid&& val) {
63+
return update_op(pos, std::forward<Monoid>(val),
7164
[](const Monoid&, const Monoid& m2) { return m2; });
7265
}
73-
constexpr auto add(int itr, Monoid&& val) {
74-
return update_op(itr, std::forward<Monoid>(val),
66+
67+
constexpr auto add(int pos, Monoid&& val) {
68+
return update_op(pos, std::forward<Monoid>(val),
7569
[](const Monoid& m1, const Monoid& m2) {
7670
return Monoid(m1.m_val + m2.m_val);
7771
});
7872
}
79-
constexpr auto query(int l, int r) const { return _query(l, r).m_val; }
80-
constexpr auto query_all() const { return m_node[0].m_val; }
73+
74+
constexpr auto query(int l, int r) const {
75+
if (l > r) return Monoid().m_val;
76+
return _query(m_root, 0, size, l, r + 1).m_val;
77+
}
78+
79+
constexpr auto query_all() const {
80+
return m_root ? m_root->val.m_val : Monoid().m_val;
81+
}
8182
};
8283

8384
} // namespace mtd

0 commit comments

Comments
 (0)