Skip to content

Commit 16b2186

Browse files
Fix test for typical_segment_tree_min; fix iterator issue of typical_segment_tree; add find_first_right method for typical_segment_tree
1 parent 0723563 commit 16b2186

File tree

5 files changed

+128
-12
lines changed

5 files changed

+128
-12
lines changed

.vscode/launch.json

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,38 @@
99
"name": "Run Extension",
1010
"type": "extensionHost",
1111
"request": "launch",
12-
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
13-
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
12+
"args": [
13+
"--extensionDevelopmentPath=${workspaceFolder}"
14+
],
15+
"outFiles": [
16+
"${workspaceFolder}/dist/**/*.js"
17+
],
1418
"preLaunchTask": "${defaultBuildTask}"
15-
}
19+
},
20+
{
21+
"name": "(gdb) 启动",
22+
"type": "cppdbg",
23+
"request": "launch",
24+
"program": "${fileDirname}/${fileBasenameNoExtension}.exe",
25+
"args": [],
26+
"stopAtEntry": false,
27+
"cwd": "${fileDirname}",
28+
"environment": [],
29+
"externalConsole": false,
30+
"MIMode": "gdb",
31+
"preLaunchTask": "C/C++: g++ 生成活动文件",
32+
"setupCommands": [
33+
{
34+
"description": "为 gdb 启用整齐打印",
35+
"text": "-enable-pretty-printing",
36+
"ignoreFailures": true
37+
},
38+
{
39+
"description": "将反汇编风格设置为 Intel",
40+
"text": "-gdb-set disassembly-flavor intel",
41+
"ignoreFailures": true
42+
},
43+
]
44+
},
1645
]
17-
}
46+
}

.vscode/tasks.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,38 @@
1616
"kind": "build",
1717
"isDefault": true
1818
}
19+
},
20+
{
21+
"type": "cppbuild",
22+
"label": "C/C++: g++ 生成活动文件",
23+
"command": "g++-9",
24+
"args": [
25+
"-fdiagnostics-color=always",
26+
"-g",
27+
"${file}",
28+
"-o",
29+
"${fileDirname}/${fileBasenameNoExtension}.exe",
30+
"-I${workspaceFolder}/library/",
31+
"-Ddebug",
32+
"-std=c++14",
33+
"-Wall",
34+
"-Wextra",
35+
"-pedantic",
36+
"-Wshadow",
37+
"-Wno-unused-parameter",
38+
"-D_GLIBCXX_DEBUG",
39+
"-D_GLIBCXX_DEBUG_PEDANTIC"
40+
],
41+
"options": {
42+
"cwd": "${fileDirname}"
43+
},
44+
"problemMatcher": [
45+
"$gcc"
46+
],
47+
"group": {
48+
"kind": "build"
49+
},
50+
"detail": "调试器生成的任务。"
1951
}
2052
]
2153
}

library/mrpython/sparse_table.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ template <typename T, typename MergeFunction> class sparse_table {
2929
size_t n = table[0].size();
3030
for (size_t i = 1; ((size_t)1 << i) <= n; ++i) {
3131
table.emplace_back();
32-
table[i].reserve(n - (1 << i) + 1);
33-
for (size_t j = 0; j < n - (1 << i) + 1; ++j)
32+
table[i].reserve(n - ((size_t)1 << i) + 1);
33+
for (size_t j = 0; j < n - ((size_t)1 << i) + 1; ++j)
3434
table[i].emplace_back(
35-
merge(table[i - 1][j], table[i - 1][j + (1 << (i - 1))]));
35+
merge(table[i - 1][j], table[i - 1][j + ((size_t)1 << (i - 1))]));
3636
}
3737
table.shrink_to_fit();
3838
}

library/mrpython/typical_segment_tree.hpp

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include <cstddef>
2+
13
#include "mrpython/bits.hpp"
24
#include "mrpython/utility.hpp"
35

@@ -56,6 +58,18 @@ template <typename T, typename MergeFunction> class typical_segment_tree {
5658
else
5759
__builtin_unreachable();
5860
}
61+
size_t data_id_to_node_id(size_t x) {
62+
x += n - ((2 * n - 1) - (highbit(2 * n - 1) - 1));
63+
if (x >= n) x -= n;
64+
x += n - 1;
65+
return x;
66+
}
67+
size_t node_id_to_data_id(size_t x) {
68+
x -= n - 1;
69+
x += ((2 * n - 1) - (highbit(2 * n - 1) - 1));
70+
if (x >= n) x -= n;
71+
return x;
72+
}
5973

6074
public:
6175
template <typename InputIterator>
@@ -65,8 +79,8 @@ template <typename T, typename MergeFunction> class typical_segment_tree {
6579
size(data.size(), 1),
6680
n(data.size()),
6781
merge(mergeFun) {
68-
rotate(data.begin(), data.begin() + (2 * n - 1) - (highbit(2 * n - 1) - 1),
69-
data.end());
82+
rotate(data.begin(),
83+
data.begin() + ((2 * n - 1) - (highbit(2 * n - 1) - 1)), data.end());
7084
reverse(data.begin(), data.end());
7185
build();
7286
}
@@ -84,6 +98,28 @@ template <typename T, typename MergeFunction> class typical_segment_tree {
8498
set_impl(target, operate, 0);
8599
}
86100
T get(size_t l, size_t r) { return get_impl(l, r, 0); }
101+
T getd(size_t l, size_t r, T const& e = {}) { return l == r ? e : get(l, r); }
102+
template <typename Check>
103+
size_t find_first_right(size_t l, Check const& check) {
104+
l = data_id_to_node_id(l);
105+
while (l % 2 == 1) l /= 2;
106+
while (l < 2 * n - 1 && check(data[l])) l = l * 2 + 1;
107+
if (l >= 2 * n - 1) return node_id_to_data_id(l / 2);
108+
T v = data[l];
109+
do {
110+
++l;
111+
if (!(l & (l + 1))) return n;
112+
while (l % 2 == 1) l /= 2;
113+
} while (!check(data[l]));
114+
while (l < n - 1) {
115+
T vl = merge(v, data[l * 2 + 1]);
116+
if (!check(vl))
117+
l = l * 2 + 2, v = vl;
118+
else
119+
l = l * 2 + 1;
120+
}
121+
return node_id_to_data_id(l);
122+
}
87123
};
88124
template <typename T>
89125
using typical_segment_tree_add = typical_segment_tree<T, std::plus<T>>;

library/test/typical_segment_tree/typical_segment_tree_min.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ TEST(typical_segment_tree, min) {
1010
q = std::uniform_int_distribution<std::size_t>{1, 5000}(gen);
1111
std::vector<int> a(n);
1212
std::uniform_int_distribution<int> val_dist(std::numeric_limits<int>::min(),
13-
std::numeric_limits<int>::min());
13+
std::numeric_limits<int>::max());
1414
std::uniform_int_distribution<std::size_t> size_dist(0, n - 1),
1515
operator_dist(0, 1);
1616
std::generate(a.begin(), a.end(), [&] { return val_dist(gen); });
@@ -19,7 +19,6 @@ TEST(typical_segment_tree, min) {
1919
if (operator_dist(gen)) {
2020
std::size_t l = size_dist(gen), r = size_dist(gen);
2121
if (l > r) std::swap(l, r);
22-
assert(l < r + 1);
2322
int ans = *std::min_element(a.begin() + l, a.begin() + r + 1);
2423
EXPECT_EQ(tree.get(l, r + 1), ans);
2524
} else {
@@ -29,4 +28,24 @@ TEST(typical_segment_tree, min) {
2928
tree.set(target, [value](int) { return value; });
3029
}
3130
}
32-
}
31+
}
32+
33+
TEST(typicaL_segment_tree, fist_first_right) {
34+
std::mt19937_64 gen(std::random_device{}());
35+
std::size_t n = std::uniform_int_distribution<std::size_t>{1, 5000}(gen),
36+
q = std::uniform_int_distribution<std::size_t>{1, 5000}(gen);
37+
std::vector<int> a(n);
38+
std::uniform_int_distribution<int> val_dist(std::numeric_limits<int>::min(),
39+
std::numeric_limits<int>::max());
40+
std::uniform_int_distribution<std::size_t> size_dist(0, n - 1),
41+
operator_dist(0, 1);
42+
std::generate(a.begin(), a.end(), [&] { return val_dist(gen); });
43+
mrpython::typical_segment_tree_min<int> tree(a.begin(), a.end());
44+
while (q--) {
45+
std::size_t l = size_dist(gen);
46+
int tv = val_dist(gen);
47+
auto check = [tv](int x) { return x <= tv; };
48+
size_t ans = std::find_if(a.begin() + l, a.end(), check) - a.begin();
49+
EXPECT_EQ(tree.find_first_right(l, check), ans);
50+
}
51+
}

0 commit comments

Comments
 (0)