atcoder/lib/data_structure/
dual_segment_tree.rs1#[derive(Clone)]
20pub struct DualSegmentTree<T, F> {
21 compose: F,
22 identity: T,
23 len: usize,
24 size: usize,
25 log: usize,
26 data: Vec<T>,
27}
28
29impl<T: Copy, F: Fn(T, T) -> T> DualSegmentTree<T, F> {
30 pub fn new(compose: F, len: usize, identity: T) -> Self {
35 Self::from_vec(vec![identity; len], compose, identity)
36 }
37
38 pub fn from_vec(values: impl Into<Vec<T>>, compose: F, identity: T) -> Self {
43 let values = values.into();
44 let len = values.len();
45 let size = len.next_power_of_two().max(1);
46 let log = size.trailing_zeros() as usize;
47 let mut data = vec![identity; size * 2];
48 data[size..size + len].copy_from_slice(&values);
49 Self {
50 compose,
51 identity,
52 len,
53 size,
54 log,
55 data,
56 }
57 }
58
59 pub fn from(compose: F, values: Vec<T>, identity: T) -> Self {
61 Self::from_vec(values, compose, identity)
62 }
63
64 fn apply_node(&mut self, index: usize, value: T) {
65 self.data[index] = (self.compose)(self.data[index], value);
66 }
67
68 fn push(&mut self, index: usize) {
69 let value = self.data[index];
70 self.apply_node(index << 1, value);
71 self.apply_node(index << 1 | 1, value);
72 self.data[index] = self.identity;
73 }
74
75 fn push_path(&mut self, index: usize) {
76 let index = index + self.size;
77 for height in (1..=self.log).rev() {
78 self.push(index >> height);
79 }
80 }
81
82 pub fn apply(&mut self, left: usize, right: usize, value: T) {
88 assert!(left <= right && right <= self.len, "range out of bounds");
89 if left == right {
90 return;
91 }
92 self.push_path(left);
93 self.push_path(right - 1);
94 let mut left = left + self.size;
95 let mut right = right + self.size;
96 while left < right {
97 if left & 1 == 1 {
98 self.apply_node(left, value);
99 left += 1;
100 }
101 if right & 1 == 1 {
102 right -= 1;
103 self.apply_node(right, value);
104 }
105 left >>= 1;
106 right >>= 1;
107 }
108 }
109
110 pub fn get(&self, index: usize) -> T {
113 assert!(index < self.len, "index out of bounds");
114 let mut index = index + self.size;
115 let mut path = Vec::with_capacity(self.log + 1);
116 while index > 0 {
117 path.push(index);
118 index >>= 1;
119 }
120 path.into_iter().fold(self.identity, |value, index| {
121 (self.compose)(value, self.data[index])
122 })
123 }
124
125 pub fn at(&self, index: usize) -> T {
129 self.get(index)
130 }
131}
132
133#[derive(Clone)]
140pub struct DualSegmentTree2D<T, F> {
141 compose: F,
142 identity: T,
143 height: usize,
144 width: usize,
145 row_size: usize,
146 column_size: usize,
147 data: Vec<T>,
148}
149
150impl<T: Copy, F: Fn(T, T) -> T> DualSegmentTree2D<T, F> {
151 pub fn new(height: usize, width: usize, compose: F, identity: T) -> Self {
155 let row_size = height.next_power_of_two().max(1);
156 let column_size = width.next_power_of_two().max(1);
157 Self {
158 compose,
159 identity,
160 height,
161 width,
162 row_size,
163 column_size,
164 data: vec![identity; 4 * row_size * column_size],
165 }
166 }
167
168 fn id(&self, row: usize, column: usize) -> usize {
169 row * (2 * self.column_size) + column
170 }
171
172 fn range_nodes(mut left: usize, mut right: usize, size: usize) -> Vec<usize> {
173 left += size;
174 right += size;
175 let mut nodes = Vec::new();
176 while left < right {
177 if left & 1 == 1 {
178 nodes.push(left);
179 left += 1;
180 }
181 if right & 1 == 1 {
182 right -= 1;
183 nodes.push(right);
184 }
185 left >>= 1;
186 right >>= 1;
187 }
188 nodes
189 }
190
191 pub fn apply(&mut self, upper: usize, lower: usize, left: usize, right: usize, value: T) {
197 assert!(
198 upper <= lower && lower <= self.height,
199 "row range out of bounds"
200 );
201 assert!(
202 left <= right && right <= self.width,
203 "column range out of bounds"
204 );
205 for row in Self::range_nodes(upper, lower, self.row_size) {
206 for column in Self::range_nodes(left, right, self.column_size) {
207 let index = self.id(row, column);
208 self.data[index] = (self.compose)(self.data[index], value);
209 }
210 }
211 }
212
213 pub fn get(&self, row: usize, column: usize) -> T {
216 assert!(
217 row < self.height && column < self.width,
218 "index out of bounds"
219 );
220 let mut rows = Vec::new();
221 let mut row = row + self.row_size;
222 while row > 0 {
223 rows.push(row);
224 row >>= 1;
225 }
226 let mut columns = Vec::new();
227 let mut column = column + self.column_size;
228 while column > 0 {
229 columns.push(column);
230 column >>= 1;
231 }
232 let mut result = self.identity;
233 for row in rows {
234 for &column in &columns {
235 result = (self.compose)(result, self.data[self.id(row, column)]);
236 }
237 }
238 result
239 }
240
241 pub fn at(&self, row: usize, column: usize) -> T {
245 self.get(row, column)
246 }
247}
248
249#[cfg(test)]
250mod tests {
251 use super::{DualSegmentTree, DualSegmentTree2D};
252
253 #[test]
254 fn applies_ranges() {
255 let mut tree = DualSegmentTree::new(|a, b| a + b, 4, 0);
256 tree.apply(0, 3, 2);
257 tree.apply(1, 4, 5);
258 assert_eq!([tree.get(0), tree.get(1), tree.get(3)], [2, 7, 5]);
259 }
260
261 #[test]
262 fn preserves_non_commutative_order() {
263 let compose = |old: (i64, i64), new: (i64, i64)| (new.0 * old.0, new.0 * old.1 + new.1);
264 let mut tree = DualSegmentTree::new(compose, 2, (1, 0));
265 tree.apply(0, 1, (2, 0));
266 tree.apply(0, 2, (1, 3));
267 assert_eq!(tree.get(0), (2, 3));
268 }
269
270 #[test]
271 fn applies_rectangles() {
272 let mut tree = DualSegmentTree2D::new(2, 3, |a, b| a + b, 0);
273 tree.apply(0, 2, 1, 3, 4);
274 assert_eq!(tree.get(1, 2), 4);
275 assert_eq!(tree.get(0, 0), 0);
276 }
277}