Skip to content

Commit 7670e46

Browse files
Deque with aggregate (#93)
* saving * progress * now ACs * finish * rename * finish docs * add source * nit --------- Co-authored-by: Luke Videckis <[email protected]> Co-authored-by: Cameron Custer <[email protected]>
1 parent e3b286d commit 7670e46

File tree

4 files changed

+278
-1
lines changed

4 files changed

+278
-1
lines changed

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ path = "examples/monotonic/count_rects.rs"
224224
name = "cartesian_tree"
225225
path = "examples/monotonic/cartesian_tree.rs"
226226

227+
[[example]]
228+
name = "deq_agg"
229+
path = "examples/data_structures/deq_agg.rs"
230+
227231
[[example]]
228232
name = "fenwick_kth"
229233
path = "examples/data_structures/fenwick_kth.rs"
@@ -238,4 +242,4 @@ path = "examples/graphs/lca_rmq_next_on_path.rs"
238242

239243
[[example]]
240244
name = "linear_rmq"
241-
path = "examples/data_structures/linear_rmq.rs"
245+
path = "examples/data_structures/linear_rmq.rs"

examples/data_structures/deq_agg.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// verification-helper: PROBLEM https://judge.yosupo.jp/problem/deque_operate_all_composite
2+
3+
use proconio::input;
4+
use programming_team_code_rust::data_structures::deq_agg::DeqAgg;
5+
use rand::{thread_rng, Rng};
6+
use std::collections::VecDeque;
7+
8+
const MOD: u64 = 998_244_353;
9+
10+
fn main() {
11+
let mut rng = thread_rng();
12+
input! {
13+
q: usize,
14+
}
15+
16+
let mut std_deq = VecDeque::new();
17+
let mut deq =
18+
DeqAgg::new(|&i: &(u64, u64), &j: &(u64, u64)| (i.0 * j.0 % MOD, (j.0 * i.1 + j.1) % MOD));
19+
20+
for _ in 0..q {
21+
input! {
22+
t: u8,
23+
}
24+
match t {
25+
0 => {
26+
input! {
27+
a: u64,
28+
b: u64,
29+
}
30+
deq.push_front((a, b));
31+
std_deq.push_front((a, b));
32+
}
33+
1 => {
34+
input! {
35+
a: u64,
36+
b: u64,
37+
}
38+
deq.push_back((a, b));
39+
std_deq.push_back((a, b));
40+
}
41+
2 => {
42+
deq.pop_front();
43+
std_deq.pop_front();
44+
}
45+
3 => {
46+
deq.pop_back();
47+
std_deq.pop_back();
48+
}
49+
_ => {
50+
input! {
51+
x: u64,
52+
}
53+
if let Some((a, b)) = deq.query() {
54+
println!("{}", (a * x + b) % MOD);
55+
} else {
56+
println!("{}", x);
57+
}
58+
}
59+
}
60+
assert_eq!(deq.len(), std_deq.len());
61+
assert_eq!(deq.is_empty(), std_deq.is_empty());
62+
assert_eq!(deq.front(), std_deq.front());
63+
assert_eq!(deq.back(), std_deq.back());
64+
if !std_deq.is_empty() {
65+
for _ in 0..3 {
66+
let i = rng.gen_range(0..deq.len());
67+
assert_eq!(deq[i], std_deq[i]);
68+
}
69+
}
70+
}
71+
}

src/data_structures/deq_agg.rs

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
//! # Deque with Aggregate
2+
3+
/// - see <https://github.com/suisen-cp/cp-library-cpp/blob/main/library/datastructure/deque_aggregation.hpp>
4+
///
5+
/// simulate a deque with 2 stacks:
6+
/// `le`, `ri` are stacks of { number, sum }
7+
/// accumulate
8+
/// <----------- -------> fold numbers from inside
9+
/// ( le ][ ri )
10+
///
11+
/// # Example
12+
/// ```
13+
/// use programming_team_code_rust::data_structures::deq_agg::DeqAgg;
14+
///
15+
/// let mut deq = DeqAgg::new(|&x, &y| std::cmp::max(x, y));
16+
/// deq.push_front(5);
17+
/// deq.push_front(3);
18+
/// deq.push_back(1);
19+
/// assert_eq!(deq[1], 5);
20+
/// assert!(std::panic::catch_unwind(|| deq[3]).is_err());
21+
/// assert_eq!(deq.query(), Some(5));
22+
/// assert_eq!(deq.front(), Some(&3));
23+
/// assert_eq!(deq.pop_front(), Some(3));
24+
/// assert_eq!(deq.back(), Some(&1));
25+
/// assert_eq!(deq.pop_back(), Some(1));
26+
/// ```
27+
pub struct DeqAgg<T, F> {
28+
le: Vec<(T, T)>,
29+
ri: Vec<(T, T)>,
30+
op: F,
31+
}
32+
33+
impl<T: Clone, F: Fn(&T, &T) -> T> DeqAgg<T, F> {
34+
/// Creates new instance of DeqAgg
35+
///
36+
/// # Complexity
37+
/// - Time: O(1)
38+
/// - Space: O(1)
39+
pub fn new(op: F) -> Self {
40+
Self {
41+
le: vec![],
42+
ri: vec![],
43+
op,
44+
}
45+
}
46+
47+
/// # Complexity
48+
/// - Time: O(1)
49+
/// - Space: O(1)
50+
pub fn len(&self) -> usize {
51+
self.le.len() + self.ri.len()
52+
}
53+
54+
/// # Complexity
55+
/// - Time: O(1)
56+
/// - Space: O(1)
57+
pub fn is_empty(&self) -> bool {
58+
self.le.is_empty() && self.ri.is_empty()
59+
}
60+
61+
/// Gets deq\[0\] op deq\[1\] op ... op deq.back(); or None if empty
62+
///
63+
/// # Complexity
64+
/// - Time: O(1)
65+
/// - Space: O(1)
66+
pub fn query(&self) -> Option<T> {
67+
if self.is_empty() {
68+
None
69+
} else if self.le.is_empty() {
70+
Some(self.ri.last().unwrap().1.clone())
71+
} else if self.ri.is_empty() {
72+
Some(self.le.last().unwrap().1.clone())
73+
} else {
74+
Some((self.op)(
75+
&self.le.last().unwrap().1,
76+
&self.ri.last().unwrap().1,
77+
))
78+
}
79+
}
80+
81+
/// Gets deq\[0\]; or None if empty
82+
///
83+
/// # Complexity
84+
/// - Time: O(1)
85+
/// - Space: O(1)
86+
pub fn front(&self) -> Option<&T> {
87+
if let Some(last) = self.le.last() {
88+
Some(&last.0)
89+
} else if !self.ri.is_empty() {
90+
Some(&self.ri[0].0)
91+
} else {
92+
None
93+
}
94+
}
95+
96+
/// Gets deq\[deq.len() - 1\]; or None if empty
97+
///
98+
/// # Complexity
99+
/// - Time: O(1)
100+
/// - Space: O(1)
101+
pub fn back(&self) -> Option<&T> {
102+
if let Some(last) = self.ri.last() {
103+
Some(&last.0)
104+
} else if !self.le.is_empty() {
105+
Some(&self.le[0].0)
106+
} else {
107+
None
108+
}
109+
}
110+
111+
/// # Complexity
112+
/// - Time: O(1)
113+
/// - Space: O(1)
114+
pub fn push_front(&mut self, elem: T) {
115+
self.le.push((
116+
elem.clone(),
117+
if let Some(last) = self.le.last() {
118+
(self.op)(&elem, &last.1)
119+
} else {
120+
elem
121+
},
122+
));
123+
}
124+
125+
/// # Complexity
126+
/// - Time: O(1)
127+
/// - Space: O(1)
128+
pub fn push_back(&mut self, elem: T) {
129+
self.ri.push((
130+
elem.clone(),
131+
if let Some(last) = self.ri.last() {
132+
(self.op)(&last.1, &elem)
133+
} else {
134+
elem
135+
},
136+
));
137+
}
138+
139+
/// Removes front, and returns it; or None if empty
140+
///
141+
/// # Complexity
142+
/// - Time: O(1) ammortized
143+
/// - Space: O(1) ammortized
144+
pub fn pop_front(&mut self) -> Option<T> {
145+
if self.le.is_empty() {
146+
let mut ary = vec![];
147+
std::mem::swap(&mut ary, &mut self.ri);
148+
self.rebuild((ary.len() + 1) / 2, ary);
149+
}
150+
self.le.pop().map(|elem| elem.0)
151+
}
152+
153+
/// Removes back, and returns it; or None if empty
154+
///
155+
/// # Complexity
156+
/// - Time: O(1) ammortized
157+
/// - Space: O(1) ammortized
158+
pub fn pop_back(&mut self) -> Option<T> {
159+
if self.ri.is_empty() {
160+
let mut ary = vec![];
161+
std::mem::swap(&mut ary, &mut self.le);
162+
ary.reverse();
163+
self.rebuild(ary.len() / 2, ary);
164+
}
165+
self.ri.pop().map(|elem| elem.0)
166+
}
167+
168+
fn rebuild(&mut self, le_len: usize, mut ary: Vec<(T, T)>) {
169+
self.ri = ary.split_off(le_len);
170+
self.le = ary;
171+
self.le.reverse();
172+
for i in 0..self.le.len() {
173+
self.le[i].1 = if i == 0 {
174+
self.le[0].0.clone()
175+
} else {
176+
(self.op)(&self.le[i].0, &self.le[i - 1].1)
177+
};
178+
}
179+
for i in 0..self.ri.len() {
180+
self.ri[i].1 = if i == 0 {
181+
self.ri[0].0.clone()
182+
} else {
183+
(self.op)(&self.ri[i - 1].1, &self.ri[i].0)
184+
};
185+
}
186+
}
187+
}
188+
189+
/// # Complexity
190+
/// - Time: O(1)
191+
/// - Space: O(1)
192+
impl<T, F> std::ops::Index<usize> for DeqAgg<T, F> {
193+
type Output = T;
194+
fn index(&self, i: usize) -> &Self::Output {
195+
if i < self.le.len() {
196+
&self.le[self.le.len() - i - 1].0
197+
} else {
198+
&self.ri[i - self.le.len()].0
199+
}
200+
}
201+
}

src/data_structures/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! # Data Structures
22
pub mod binary_trie;
3+
pub mod deq_agg;
34
pub mod disjoint_rmq;
45
pub mod fenwick;
56
pub mod lazy_seg_tree;

0 commit comments

Comments
 (0)