Skip to content

Commit 65720e0

Browse files
Add typical segment tree template
1 parent a985ae7 commit 65720e0

File tree

16 files changed

+300
-13
lines changed

16 files changed

+300
-13
lines changed

.vscode/settings.json

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,70 @@
1111
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
1212
"typescript.tsc.autoDetect": "off",
1313
"files.associations": {
14-
"limits": "cpp"
14+
"limits": "cpp",
15+
"vector": "cpp",
16+
"cctype": "cpp",
17+
"clocale": "cpp",
18+
"cmath": "cpp",
19+
"cstdarg": "cpp",
20+
"cstddef": "cpp",
21+
"cstdio": "cpp",
22+
"cstdlib": "cpp",
23+
"ctime": "cpp",
24+
"cwchar": "cpp",
25+
"cwctype": "cpp",
26+
"any": "cpp",
27+
"array": "cpp",
28+
"atomic": "cpp",
29+
"bit": "cpp",
30+
"*.tcc": "cpp",
31+
"charconv": "cpp",
32+
"chrono": "cpp",
33+
"compare": "cpp",
34+
"concepts": "cpp",
35+
"condition_variable": "cpp",
36+
"cstdint": "cpp",
37+
"deque": "cpp",
38+
"list": "cpp",
39+
"map": "cpp",
40+
"set": "cpp",
41+
"string": "cpp",
42+
"unordered_map": "cpp",
43+
"exception": "cpp",
44+
"algorithm": "cpp",
45+
"functional": "cpp",
46+
"iterator": "cpp",
47+
"memory": "cpp",
48+
"memory_resource": "cpp",
49+
"numeric": "cpp",
50+
"optional": "cpp",
51+
"random": "cpp",
52+
"ratio": "cpp",
53+
"string_view": "cpp",
54+
"system_error": "cpp",
55+
"tuple": "cpp",
56+
"type_traits": "cpp",
57+
"utility": "cpp",
58+
"format": "cpp",
59+
"fstream": "cpp",
60+
"initializer_list": "cpp",
61+
"iomanip": "cpp",
62+
"iosfwd": "cpp",
63+
"iostream": "cpp",
64+
"istream": "cpp",
65+
"mutex": "cpp",
66+
"new": "cpp",
67+
"numbers": "cpp",
68+
"ostream": "cpp",
69+
"semaphore": "cpp",
70+
"span": "cpp",
71+
"sstream": "cpp",
72+
"stdexcept": "cpp",
73+
"stop_token": "cpp",
74+
"streambuf": "cpp",
75+
"thread": "cpp",
76+
"typeinfo": "cpp",
77+
"variant": "cpp",
78+
"text_encoding": "cpp"
1579
}
1680
}

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
## features
66

77
- [ST 表](./library/mrpython/sparse_table.hpp)
8+
- [无标记线段树](./library/mrpython/typical_segment_tree.hpp)
89

910
## license
1011

library/makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ $(TARGET): $(SRCS)
2020
$(CXX) $(CXXFLAGS) -o $(TARGET) $(SRCS) $(LDFLAGS)
2121

2222
clean:
23-
rm -f $(TARGET)
23+
rm -f $(TARGET) *.d
2424

2525
.PHONY: all clean

library/mrpython/bits.hpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#ifndef MP_LIBRARY_BITS
2+
#define MP_LIBRARY_BITS
3+
#include <limits>
4+
namespace mrpython {
5+
unsigned countl_zero(unsigned x) { return __builtin_clz(x); }
6+
unsigned countl_zero(unsigned long x) { return __builtin_clzl(x); }
7+
unsigned countl_zero(unsigned long long x) { return __builtin_clzll(x); }
8+
unsigned countr_zero(unsigned x) { return __builtin_ctz(x); }
9+
unsigned countr_zero(unsigned long x) { return __builtin_ctzl(x); }
10+
unsigned countr_zero(unsigned long long x) { return __builtin_ctzll(x); }
11+
unsigned int_log2(unsigned n) {
12+
return std::numeric_limits<unsigned>::digits - 1 - countl_zero(n);
13+
}
14+
unsigned long int_log2(unsigned long n) {
15+
return std::numeric_limits<unsigned long>::digits - 1 - countl_zero(n);
16+
}
17+
unsigned long long int_log2(unsigned long long n) {
18+
return std::numeric_limits<unsigned long long>::digits - 1 - countl_zero(n);
19+
}
20+
unsigned lowbit(unsigned x) { return x & -x; }
21+
unsigned long lowbit(unsigned long x) { return x & -x; }
22+
unsigned long long lowbit(unsigned long long x) { return x & -x; }
23+
unsigned highbit(unsigned x) { return (unsigned)1 << int_log2(x); }
24+
unsigned long highbit(unsigned long x) {
25+
return (unsigned long)1 << int_log2(x);
26+
}
27+
unsigned long long highbit(unsigned long long x) {
28+
return (unsigned long long)1 << int_log2(x);
29+
}
30+
} // namespace mrpython
31+
#endif

library/mrpython/sparse_table.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include "mrpython/bits.hpp"
12
#include "mrpython/utility.hpp"
23

34
#ifndef MP_LIBRARY_SPARSE_TABLE_HPP
@@ -36,8 +37,7 @@ template <typename T, typename MergeFunction> class sparse_table {
3637
table.shrink_to_fit();
3738
}
3839
T get(size_t l, size_t r) const {
39-
size_t k =
40-
std::numeric_limits<long long int>::digits - __builtin_clzll(r - l);
40+
size_t k = int_log2(r - l);
4141
return merge(table[k][l], table[k][r - ((size_t)1 << k)]);
4242
}
4343
};
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#include "mrpython/bits.hpp"
2+
#include "mrpython/utility.hpp"
3+
4+
#ifndef MP_LIBRARY_SEGMENT_TREE_HPP
5+
#define MP_LIBRARY_SEGMENT_TREE_HPP
6+
#include <algorithm>
7+
#include <iterator>
8+
#include <utility>
9+
#include <vector>
10+
11+
namespace mrpython {
12+
using std::size_t;
13+
/**
14+
* 一颗 无标记线段树 模板。
15+
* @tparam T 元素类型
16+
* @tparam MergeFunction 合并运算函数,对于函数 `F` 应满足结合律
17+
*/
18+
template <typename T, typename MergeFunction> class typical_segment_tree {
19+
std::vector<T> data;
20+
std::vector<size_t> size;
21+
size_t n;
22+
MergeFunction merge;
23+
void build(void) {
24+
data.reserve(2 * n - 1), size.reserve(2 * n - 1);
25+
for (size_t i = n; i < 2 * n - 1; ++i) {
26+
size_t d = 2 * n - 1 - i;
27+
size_t l = d * 2 + 1, r = d * 2;
28+
data.emplace_back(merge(data[2 * n - 1 - l], data[2 * n - 1 - r]));
29+
size.emplace_back(size[2 * n - 1 - l] + size[2 * n - 1 - r]);
30+
}
31+
std::reverse(data.begin(), data.end());
32+
std::reverse(size.begin(), size.end());
33+
}
34+
template <typename Fun>
35+
void set_impl(size_t c, Fun const& operate, size_t pos) {
36+
if (size[pos] == 1) {
37+
data[pos] = operate((T const&)data[pos]);
38+
return;
39+
}
40+
size_t m = size[pos * 2 + 1];
41+
if (c < m)
42+
set_impl(c, operate, pos * 2 + 1);
43+
else
44+
set_impl(c - m, operate, pos * 2 + 2);
45+
data[pos] = merge(data[pos * 2 + 1], data[pos * 2 + 2]);
46+
}
47+
T get_impl(size_t l, size_t r, size_t pos) {
48+
if (l == 0 && r == size[pos]) return data[pos];
49+
size_t m = size[pos * 2 + 1];
50+
if (l < m && r > m)
51+
return merge(get_impl(l, m, pos * 2 + 1),
52+
get_impl(0, r - m, pos * 2 + 2));
53+
if (l < m) return get_impl(l, r, pos * 2 + 1);
54+
if (r > m) return get_impl(l - m, r - m, pos * 2 + 2);
55+
throw;
56+
}
57+
58+
public:
59+
template <typename InputIterator>
60+
typical_segment_tree(InputIterator first, InputIterator last,
61+
MergeFunction mergeFun = MergeFunction())
62+
: data(first, last),
63+
size(data.size(), 1),
64+
n(data.size()),
65+
merge(mergeFun) {
66+
rotate(data.begin(), data.begin() + (2 * n - 1) - (highbit(2 * n - 1) - 1),
67+
data.end());
68+
reverse(data.begin(), data.end());
69+
build();
70+
}
71+
typical_segment_tree(size_t n, T const& init,
72+
MergeFunction mergeFun = MergeFunction())
73+
: data(n, init), size(n, 1), n(n), merge(mergeFun) {
74+
build();
75+
}
76+
/**
77+
* 单点修改操作
78+
* @param target 修改的位置
79+
* @param operate 更新该点的函数
80+
*/
81+
template <typename Fun> void set(size_t target, Fun const& operate) {
82+
set_impl(target, operate, 0);
83+
}
84+
T get(size_t l, size_t r) { return get_impl(l, r, 0); }
85+
};
86+
template <typename T>
87+
using typical_segment_tree_add = typical_segment_tree<T, std::plus<T>>;
88+
template <typename T>
89+
using typical_segment_tree_max = typical_segment_tree<T, max>;
90+
template <typename T>
91+
using typical_segment_tree_min = typical_segment_tree<T, min>;
92+
} // namespace mrpython
93+
#endif // MP_LIBRARY_SEGMENT_TREE_HPP

library/mrpython/utility.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef MP_LIBRARY_UTILITY_HPP
22
#define MP_LIBRARY_UTILITY_HPP
33
#include <algorithm>
4+
#include <limits>
45

56
namespace mrpython {
67
struct max {
@@ -39,6 +40,5 @@ template <typename Comp> struct compare_iterator {
3940
return comp(*a, *b) ? a : b;
4041
}
4142
};
42-
4343
} // namespace mrpython
4444
#endif // MP_LIBRARY_UTILITY_HPP

library/test/all.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
#include "test/sparse_table/all.hpp"
1+
#include "sparse_table/all.hpp"
2+
#include "typical_segment_tree/all.hpp"

library/test/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include <gtest/gtest.h>
22

3-
#include "test/all.hpp"
3+
#include "all.hpp"
44

55
GTEST_API_ int main(int argc, char** argv) {
66
testing::InitGoogleTest(&argc, argv);

library/test/main.o

-971 KB
Binary file not shown.

0 commit comments

Comments
 (0)