Skip to content

Commit 27dd9c7

Browse files
seg tree (#37)
1 parent e58c615 commit 27dd9c7

File tree

5 files changed

+215
-0
lines changed

5 files changed

+215
-0
lines changed

Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,18 @@ path = "examples/data_structures/fenwick_aizu.rs"
3030
name = "fenwick_yosupo"
3131
path = "examples/data_structures/fenwick_yosupo.rs"
3232

33+
[[example]]
34+
name = "lazy_seg_tree"
35+
path = "examples/data_structures/lazy_seg_tree.rs"
36+
3337
[[example]]
3438
name = "rmq"
3539
path = "examples/data_structures/rmq.rs"
3640

41+
[[example]]
42+
name = "seg_tree_build_on_array"
43+
path = "examples/data_structures/seg_tree_build_on_array.rs"
44+
3745
[[example]]
3846
name = "trie"
3947
path = "examples/data_structures/trie.rs"
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// verification-helper: PROBLEM https://onlinejudge.u-aizu.ac.jp/courses/library/3/DSL/all/DSL_2_G
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 mut seg_tree = SegTree::new(n);
13+
for _ in 0..q {
14+
input! {
15+
t: usize
16+
}
17+
18+
match t {
19+
0 => {
20+
input! {
21+
le: usize,
22+
ri: usize,
23+
delta: u64
24+
}
25+
seg_tree.update(le - 1, ri, delta);
26+
}
27+
1 => {
28+
input! {
29+
le: usize,
30+
ri: usize
31+
}
32+
println!("{}", seg_tree.query(le - 1, ri));
33+
}
34+
_ => unreachable!(),
35+
}
36+
}
37+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// verification-helper: PROBLEM https://judge.yosupo.jp/problem/point_add_range_sum
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+
a: [u64; n]
11+
}
12+
13+
let mut seg_tree = SegTree::build_on_array(&a);
14+
for _ in 0..q {
15+
input! {
16+
t: usize
17+
}
18+
19+
match t {
20+
0 => {
21+
input! {
22+
p: usize,
23+
x: u64
24+
}
25+
seg_tree.update(p, p + 1, x);
26+
}
27+
1 => {
28+
input! {
29+
le: usize,
30+
ri: usize
31+
}
32+
println!("{}", seg_tree.query(le, ri));
33+
}
34+
_ => unreachable!(),
35+
}
36+
}
37+
}

src/data_structures/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ pub mod binary_trie;
33
pub mod dsu;
44
pub mod fenwick;
55
pub mod rmq;
6+
pub mod seg_tree;
67
pub mod trie;

src/data_structures/seg_tree.rs

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

0 commit comments

Comments
 (0)