snippets 0.1.0
Loading...
Searching...
No Matches
segment_tree.hpp
Go to the documentation of this file.
1// adapted from https://oi-wiki.org/ds/seg/
2
3#ifndef SEGMENT_TREE_H
4#define SEGMENT_TREE_H
5
6#include <vector>
7#include <concepts>
8
9namespace hsc_snippets
10{
11 template <std::integral T>
13 {
14 private:
15 const int n;
16 std::vector<T> d;
17 std::vector<T> lazy_tag;
18 void build(const std::vector<T> &a, int s, int t, int p)
19 {
20 if (s == t)
21 {
22 d[p] = a[s];
23 return;
24 }
25 int m = s + ((t - s) >> 1);
26 build(a, s, m, p * 2), build(a, m + 1, t, p * 2 + 1);
27 d[p] = d[p * 2] + d[(p * 2) + 1];
28 }
29 T _range_sum(int l, int r, int s, int t, int p)
30 {
31 if (l <= s && t <= r)
32 return d[p];
33 int m = s + ((t - s) >> 1), sum = 0;
34 maintain(s, t, p);
35 if (l <= m)
36 sum += _range_sum(l, r, s, m, p * 2);
37 if (r > m)
38 sum += _range_sum(l, r, m + 1, t, p * 2 + 1);
39 return sum;
40 }
41 void maintain(int cl, int cr, int p)
42 {
43 int cm = cl + (cr - cl) / 2;
44 if (cl != cr && lazy_tag[p])
45 {
46 lazy_tag[p * 2] += lazy_tag[p];
47 lazy_tag[p * 2 + 1] += lazy_tag[p];
48 d[p * 2] += lazy_tag[p] * (cm - cl + 1);
49 d[p * 2 + 1] += lazy_tag[p] * (cr - cm);
50 lazy_tag[p] = 0;
51 }
52 }
53 void _range_set(int l, int r, T val, int cl, int cr, int p)
54 {
55 if (l <= cl && cr <= r)
56 {
57 lazy_tag[p] = val;
58 d[p] = (cr - cl + 1) * val;
59 return;
60 }
61 int m = cl + (cr - cl) / 2;
62 maintain(cl, cr, p);
63 if (l <= m)
64 _range_set(l, r, val, cl, m, p * 2);
65 if (r > m)
66 _range_set(l, r, val, m + 1, cr, p * 2 + 1);
67 d[p] = d[p * 2] + d[p * 2 + 1];
68 }
69 void _range_add(int l, int r, T val, int cl, int cr, int p)
70 {
71 if (l <= cl && cr <= r)
72 {
73 lazy_tag[p] += val;
74 d[p] += (cr - cl + 1) * val;
75 return;
76 }
77 int m = cl + (cr - cl) / 2;
78 maintain(cl, cr, p);
79 if (l <= m)
80 _range_add(l, r, val, cl, m, p * 2);
81 if (r > m)
82 _range_add(l, r, val, m + 1, cr, p * 2 + 1);
83 d[p] = d[p * 2] + d[p * 2 + 1];
84 }
85
86 public:
87 explicit SegmentTree(const std::vector<T> &a) : n(a.size())
88 {
89 auto vector_size = n << 2;
90 d = std::vector<T>(vector_size);
91 lazy_tag = std::vector<T>(vector_size, 0);
92 build(a, 0, n - 1, 1);
93 }
99 T range_sum(int left, int right)
100 {
101 return _range_sum(left, right, 0, n - 1, 1);
102 }
103
110 void range_set(int left, int right, T value) { _range_set(left, right, value, 0, n - 1, 1); }
111
118 void range_add(int left, int right, T value) { _range_add(left, right, value, 0, n - 1, 1); }
119
123 int size() const { return n; }
124 };
125}
126#endif // SEGMENT_TREE_H
Definition segment_tree.hpp:13
void range_add(int left, int right, T value)
Definition segment_tree.hpp:118
T range_sum(int left, int right)
Definition segment_tree.hpp:99
int size() const
Definition segment_tree.hpp:123
void range_set(int left, int right, T value)
Definition segment_tree.hpp:110
SegmentTree(const std::vector< T > &a)
Definition segment_tree.hpp:87
Definition big_integer.hpp:14
T sum(T x)
Definition varadic_numeric.hpp:64