Skip to content

Commit c2b04a3

Browse files
authored
Point seg tree (#51)
* finished refactor * still has bugs * saving progress * nits * now AC's!!!!!!!!!!! * now ACs on yosupo * fix cargo test * finish docs * now works with capturing vars * golf * saving progress * fmt * nit * fix test --------- Co-authored-by: Luke Videckis <lukevideckis@gmail.com>
1 parent 1f48e7a commit c2b04a3

File tree

8 files changed

+286
-103
lines changed

8 files changed

+286
-103
lines changed

Cargo.toml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ name = "rmq"
3939
path = "examples/data_structures/rmq.rs"
4040

4141
[[example]]
42-
name = "seg_tree_build_on_array"
43-
path = "examples/data_structures/seg_tree_build_on_array.rs"
42+
name = "lazy_seg_tree_build_on_array"
43+
path = "examples/data_structures/lazy_seg_tree_build_on_array.rs"
4444

4545
[[example]]
4646
name = "trie"
@@ -89,3 +89,11 @@ path = "examples/numbers/primes_is_prime.rs"
8989
[[example]]
9090
name = "manacher"
9191
path = "examples/strings/manacher.rs"
92+
93+
[[example]]
94+
name = "seg_tree_yosupo"
95+
path = "examples/data_structures/seg_tree_yosupo.rs"
96+
97+
[[example]]
98+
name = "seg_tree_aizu"
99+
path = "examples/data_structures/seg_tree_aizu.rs"

examples/data_structures/lazy_seg_tree.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
// verification-helper: PROBLEM https://onlinejudge.u-aizu.ac.jp/courses/library/3/DSL/all/DSL_2_G
22

33
use proconio::input;
4-
use programming_team_code_rust::data_structures::seg_tree::SegTree;
4+
use programming_team_code_rust::data_structures::lazy_seg_tree::LazySegTree;
55

66
fn main() {
77
input! {
88
n: usize,
99
q: usize
1010
}
1111

12-
let mut seg_tree = SegTree::new(n);
12+
let mut seg_tree = LazySegTree::new(n);
1313
for _ in 0..q {
1414
input! {
1515
t: usize

examples/data_structures/seg_tree_build_on_array.rs renamed to examples/data_structures/lazy_seg_tree_build_on_array.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// verification-helper: PROBLEM https://judge.yosupo.jp/problem/point_add_range_sum
22

33
use proconio::input;
4-
use programming_team_code_rust::data_structures::seg_tree::SegTree;
4+
use programming_team_code_rust::data_structures::lazy_seg_tree::LazySegTree;
55

66
fn main() {
77
input! {
@@ -10,7 +10,7 @@ fn main() {
1010
a: [u64; n]
1111
}
1212

13-
let mut seg_tree = SegTree::build_on_array(&a);
13+
let mut seg_tree = LazySegTree::build_on_array(&a);
1414
for _ in 0..q {
1515
input! {
1616
t: usize
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// verification-helper: PROBLEM https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_B
2+
3+
use proconio::input;
4+
use programming_team_code_rust::data_structures::seg_tree::SegTree;
5+
6+
fn main() {
7+
input! {
8+
n: usize,
9+
q: usize,
10+
}
11+
let mut st = SegTree::<usize>::new(n, |x, y| x + y, 0);
12+
for _ in 0..q {
13+
input! {
14+
t: u8,
15+
}
16+
match t {
17+
0 => {
18+
input! {
19+
i: usize,
20+
x: usize,
21+
}
22+
st.set(i - 1, st.query(i - 1..i) + x);
23+
}
24+
_ => {
25+
input! {
26+
le: usize,
27+
ri: usize,
28+
}
29+
println!("{}", st.query(le - 1..ri));
30+
}
31+
}
32+
}
33+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// verification-helper: PROBLEM https://judge.yosupo.jp/problem/point_set_range_composite
2+
3+
use proconio::input;
4+
use programming_team_code_rust::data_structures::seg_tree::SegTree;
5+
6+
fn main() {
7+
input! {
8+
n: usize,
9+
q: usize
10+
}
11+
12+
let a = (0..n)
13+
.map(|_| {
14+
input! {
15+
c: usize,
16+
d: usize
17+
}
18+
(c, d)
19+
})
20+
.collect::<Vec<(usize, usize)>>();
21+
22+
let mut seg_tree = SegTree::<(usize, usize)>::build_on_array(
23+
&a,
24+
move |x, y| (x.0 * y.0 % 998244353, (y.0 * x.1 + y.1) % 998244353),
25+
(1, 0),
26+
);
27+
28+
for _ in 0..q {
29+
input! {
30+
t: usize
31+
}
32+
33+
match t {
34+
0 => {
35+
input! {
36+
idx: usize,
37+
c: usize,
38+
d: usize
39+
}
40+
seg_tree.set(idx, (c, d));
41+
}
42+
_ => {
43+
input! {
44+
le: usize,
45+
ri: usize,
46+
x: usize
47+
}
48+
let (c, d) = seg_tree.query(le..ri);
49+
println!("{}", (c * x + d) % 998244353);
50+
}
51+
}
52+
}
53+
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
//! # Lazy Segment Tree
2+
3+
use std::ops::Range;
4+
5+
/// see https://codeforces.com/blog/entry/112755
6+
///
7+
/// returns the split point of the range which
8+
/// makes the segment tree a complete binary tree
9+
fn split(tr: &Range<usize>) -> usize {
10+
let pw2 = 1 << tr.len().ilog2();
11+
(tr.start + pw2).min(tr.end - pw2 / 2)
12+
}
13+
14+
fn op(vl: u64, vr: u64) -> u64 {
15+
vl + vr
16+
}
17+
18+
/// # Example
19+
/// ```
20+
/// use programming_team_code_rust::data_structures::lazy_seg_tree::LazySegTree;
21+
///
22+
/// let mut seg_tree = LazySegTree::new(10);
23+
/// seg_tree.update(0..5, 1);
24+
/// seg_tree.update(5..10, 2);
25+
/// assert_eq!(seg_tree.query(0..10), 15);
26+
/// ```
27+
pub struct LazySegTree {
28+
n: usize,
29+
tree: Vec<u64>,
30+
lazy: Vec<u64>,
31+
}
32+
33+
impl LazySegTree {
34+
/// Creates a new segment tree with n elements
35+
///
36+
/// # Complexity
37+
/// - Time: O(n)
38+
/// - Space: O(n)
39+
pub fn new(n: usize) -> Self {
40+
LazySegTree {
41+
n,
42+
tree: vec![0; 2 * n],
43+
lazy: vec![0; n],
44+
}
45+
}
46+
47+
/// Constructs a segment tree on a given array
48+
///
49+
/// # Complexity
50+
/// - Time: O(n)
51+
/// - Space: O(n)
52+
pub fn build_on_array(a: &[u64]) -> Self {
53+
let n = a.len();
54+
let mut pw2 = 1;
55+
while pw2 < n {
56+
pw2 *= 2;
57+
}
58+
let mut tree = vec![0; 2 * n];
59+
for i in 0..n {
60+
tree[(i + pw2) % n + n] = a[i];
61+
}
62+
for i in (1..n).rev() {
63+
tree[i] = op(tree[2 * i], tree[2 * i + 1]);
64+
}
65+
LazySegTree {
66+
n,
67+
tree,
68+
lazy: vec![0; n],
69+
}
70+
}
71+
72+
fn apply(&mut self, delta: u64, tr: &Range<usize>, v: usize) {
73+
self.tree[v] += delta * tr.len() as u64;
74+
if v < self.n {
75+
self.lazy[v] += delta;
76+
}
77+
}
78+
79+
fn push(&mut self, tr: &Range<usize>, v: usize) {
80+
if self.lazy[v] > 0 {
81+
let tm = split(tr);
82+
self.apply(self.lazy[v], &(tr.start..tm), 2 * v);
83+
self.apply(self.lazy[v], &(tm..tr.end), 2 * v + 1);
84+
self.lazy[v] = 0;
85+
}
86+
}
87+
88+
/// Updates the range [qr.start, qr.end) by adding delta to each element
89+
/// in the range
90+
///
91+
/// # Complexity
92+
/// - Time: O(log(n))
93+
/// - Space: O(log(n)) due to the program stack
94+
pub fn update(&mut self, qr: Range<usize>, delta: u64) {
95+
self.update_impl(&qr, delta, &(0..self.n), 1);
96+
}
97+
98+
fn update_impl(&mut self, qr: &Range<usize>, delta: u64, tr: &Range<usize>, v: usize) {
99+
if qr.end <= tr.start || tr.end <= qr.start {
100+
return;
101+
}
102+
if qr.start <= tr.start && tr.end <= qr.end {
103+
return self.apply(delta, tr, v);
104+
}
105+
self.push(tr, v);
106+
let tm = split(tr);
107+
self.update_impl(qr, delta, &(tr.start..tm), 2 * v);
108+
self.update_impl(qr, delta, &(tm..tr.end), 2 * v + 1);
109+
self.tree[v] = op(self.tree[2 * v], self.tree[2 * v + 1]);
110+
}
111+
112+
/// Queries the range [qr.start, qr.end)
113+
///
114+
/// # Complexity
115+
/// - Time: O(log(n))
116+
/// - Space: O(log(n)) due to the program stack
117+
pub fn query(&mut self, qr: Range<usize>) -> u64 {
118+
self.query_impl(&qr, &(0..self.n), 1)
119+
}
120+
121+
fn query_impl(&mut self, qr: &Range<usize>, tr: &Range<usize>, v: usize) -> u64 {
122+
if qr.end <= tr.start || tr.end <= qr.start {
123+
return 0;
124+
}
125+
if qr.start <= tr.start && tr.end <= qr.end {
126+
return self.tree[v];
127+
}
128+
self.push(tr, v);
129+
let tm = split(tr);
130+
op(
131+
self.query_impl(qr, &(tr.start..tm), 2 * v),
132+
self.query_impl(qr, &(tm..tr.end), 2 * v + 1),
133+
)
134+
}
135+
}

src/data_structures/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
pub mod binary_trie;
33
pub mod dsu;
44
pub mod fenwick;
5+
pub mod lazy_seg_tree;
56
pub mod rmq;
67
pub mod seg_tree;
78
pub mod trie;

0 commit comments

Comments
 (0)