Skip to content

Commit bc726d3

Browse files
committed
feat: Add SegmentTreeHeapSon implementation and update test cases to utilize it
1 parent 8f4b21c commit bc726d3

File tree

3 files changed

+114
-1
lines changed

3 files changed

+114
-1
lines changed

test/point_set_range_composite.test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ int main() {
3636
affines.emplace_back(a, b);
3737
}
3838

39-
SegmentTree<SegmentTreeStoreSon<AffineMonoid>> sgt(affines);
39+
SegmentTree<SegmentTreeHeapSon<AffineMonoid>> sgt(affines);
4040
while (q--) {
4141
size_t op;
4242
cin >> op;
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#define PROBLEM "https://judge.yosupo.jp/problem/point_set_range_composite"
2+
3+
#include "../weilycoder/ds/segment_tree.hpp"
4+
#include <cstdint>
5+
#include <iostream>
6+
#include <vector>
7+
using namespace std;
8+
using namespace weilycoder;
9+
10+
static constexpr uint64_t mod = 998244353;
11+
12+
struct AffineMonoid {
13+
using value_type = pair<uint64_t, uint64_t>; // (a, b) represents f(x) = a * x + b
14+
15+
static value_type identity() { return {1, 0}; }
16+
static value_type operation(const value_type &f, const value_type &g) {
17+
return {(g.first * f.first) % mod, (g.first * f.second + g.second) % mod};
18+
}
19+
20+
static uint64_t affine(const value_type &f, uint64_t x) {
21+
return (f.first * x + f.second) % mod;
22+
}
23+
};
24+
25+
int main() {
26+
cin.tie(nullptr)->sync_with_stdio(false);
27+
cin.exceptions(cin.badbit | cin.failbit);
28+
size_t n, q;
29+
cin >> n >> q;
30+
31+
vector<pair<uint64_t, uint64_t>> affines;
32+
affines.reserve(n);
33+
for (size_t i = 0; i < n; ++i) {
34+
uint64_t a, b;
35+
cin >> a >> b;
36+
affines.emplace_back(a, b);
37+
}
38+
39+
SegmentTree<SegmentTreeStoreSon<AffineMonoid>> sgt(affines);
40+
while (q--) {
41+
size_t op;
42+
cin >> op;
43+
if (op == 0) {
44+
size_t p;
45+
uint64_t c, d;
46+
cin >> p >> c >> d;
47+
sgt.point_set(p, {c, d});
48+
} else {
49+
size_t l, r;
50+
uint64_t x;
51+
cin >> l >> r >> x;
52+
auto func = sgt.range_query(l, r);
53+
cout << AffineMonoid::affine(func, x) << '\n';
54+
}
55+
}
56+
return 0;
57+
}

weilycoder/ds/segment_tree.hpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,62 @@
1212
#include <vector>
1313

1414
namespace weilycoder {
15+
template <typename _Monoid, typename _ptr_t = size_t> struct SegmentTreeHeapSon {
16+
protected:
17+
using T = typename _Monoid::value_type;
18+
using ptr_t = _ptr_t;
19+
using Monoid = _Monoid;
20+
static constexpr ptr_t null = std::numeric_limits<ptr_t>::max();
21+
22+
private:
23+
ptr_t st, ed;
24+
std::vector<T> data;
25+
26+
void init(ptr_t node, ptr_t l, ptr_t r, const std::vector<T> &arr) {
27+
if (r - l == 1) {
28+
data[node] = arr[l];
29+
} else {
30+
ptr_t mid = l + ((r - l) >> 1);
31+
init(node * 2 + 1, l, mid, arr), init(node * 2 + 2, mid, r, arr);
32+
pushup(node);
33+
}
34+
}
35+
36+
protected:
37+
ptr_t get_st() const { return st; }
38+
ptr_t get_ed() const { return ed; }
39+
40+
T &get_value(ptr_t node) { return data[node]; }
41+
const T &get_value(ptr_t node) const { return data[node]; }
42+
43+
ptr_t get_lc(ptr_t node) const { return node * 2 + 1; }
44+
ptr_t get_rc(ptr_t node) const { return node * 2 + 2; }
45+
46+
void pushdown(ptr_t node) const {}
47+
void pushup(ptr_t node) {
48+
data[node] = Monoid::operation(data[get_lc(node)], data[get_rc(node)]);
49+
}
50+
51+
explicit SegmentTreeHeapSon(ptr_t size) : st(0), ed(size) {
52+
data.resize(size * 4, Monoid::identity());
53+
}
54+
55+
explicit SegmentTreeHeapSon(ptr_t st, ptr_t ed) : st(st), ed(ed) {
56+
data.resize((ed - st) * 4, Monoid::identity());
57+
}
58+
59+
explicit SegmentTreeHeapSon(const std::vector<T> &arr)
60+
: st(0), ed(static_cast<ptr_t>(arr.size())) {
61+
data.resize(arr.size() * 4, Monoid::identity());
62+
init(0, st, ed, arr);
63+
}
64+
};
65+
66+
/**
67+
* @brief Segment Tree Base Class that stores child pointers
68+
* @tparam _Monoid The monoid defining the operation and identity
69+
* @tparam _ptr_t The pointer type used for indexing nodes (default: size_t)
70+
*/
1571
template <typename _Monoid, typename _ptr_t = size_t> struct SegmentTreeStoreSon {
1672
protected:
1773
using T = typename _Monoid::value_type;

0 commit comments

Comments
 (0)