Skip to content

Commit 43248da

Browse files
authored
Bit walk (#88)
* bit walk * add example * different interface actually * fix docs * Update fenwick.rs --------- Co-authored-by: Luke Videckis <lukevideckis@gmail.com>
1 parent 41528c4 commit 43248da

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,10 @@ path = "examples/monotonic/count_rects.rs"
216216
name = "cartesian_tree"
217217
path = "examples/monotonic/cartesian_tree.rs"
218218

219+
[[example]]
220+
name = "fenwick_kth"
221+
path = "examples/data_structures/fenwick_kth.rs"
222+
219223
[[example]]
220224
name = "disjoint_rmq_non_commutative"
221225
path = "examples/data_structures/disjoint_rmq_non_commutative.rs"
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// verification-helper: PROBLEM https://judge.yosupo.jp/problem/predecessor_problem
2+
3+
use proconio::input;
4+
use programming_team_code_rust::data_structures::fenwick::Fenwick;
5+
6+
fn main() {
7+
input! {
8+
n: usize,
9+
q: usize,
10+
s: String,
11+
}
12+
13+
let mut fenwick =
14+
Fenwick::<i32>::build_on_array(&s.chars().map(|c| (c == '1') as i32).collect::<Vec<_>>());
15+
16+
for _ in 0..q {
17+
input! {
18+
t: u8,
19+
k: usize,
20+
}
21+
match t {
22+
0 => {
23+
if fenwick.sum(k..k + 1) == 0 {
24+
fenwick.add(k, 1);
25+
}
26+
}
27+
1 => {
28+
if fenwick.sum(k..k + 1) == 1 {
29+
fenwick.add(k, -1);
30+
}
31+
}
32+
2 => {
33+
println!("{}", fenwick.sum(k..k + 1));
34+
}
35+
3 => {
36+
let cnt = fenwick.sum(0..k);
37+
let res = fenwick.kth(cnt + 1);
38+
if res == n {
39+
println!("-1");
40+
} else {
41+
println!("{}", res);
42+
}
43+
}
44+
_ => {
45+
let cnt_le = fenwick.sum(0..k + 1);
46+
if cnt_le == 0 {
47+
println!("-1");
48+
} else {
49+
println!("{}", fenwick.kth(cnt_le));
50+
}
51+
}
52+
}
53+
}
54+
}

src/data_structures/fenwick.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
/// fenwick.add(2, 2);
1010
/// fenwick.add(3, 1);
1111
/// assert_eq!(fenwick.sum(1..3), 5);
12+
/// assert_eq!(fenwick.kth(5), 2);
13+
/// assert!(std::panic::catch_unwind(|| fenwick.kth(0)).is_err());
1214
/// ```
1315
pub struct Fenwick<T> {
1416
ary: Vec<T>,
@@ -75,4 +77,28 @@ impl<T: Clone + Default + std::ops::AddAssign<T>> Fenwick<T> {
7577
{
7678
self.accum(range.end) - self.accum(range.start)
7779
}
80+
81+
/// Gets maximum pos such that sum of [0, pos) < sum
82+
///
83+
/// Requires fenwick.sum(i..i + 1) >= 0 and sum > 0
84+
///
85+
/// # Complexity
86+
/// - Time: O(log n)
87+
/// - Space: O(1)
88+
pub fn kth(&self, mut sum: T) -> usize
89+
where
90+
T: std::ops::SubAssign<T> + std::cmp::PartialOrd,
91+
{
92+
assert!(sum > T::default());
93+
let mut pos = 0;
94+
let mut pw = self.ary.len().next_power_of_two();
95+
while pw > 0 {
96+
if pos + pw <= self.ary.len() && self.ary[pos + pw - 1] < sum {
97+
pos += pw;
98+
sum -= self.ary[pos - 1].clone();
99+
}
100+
pw /= 2;
101+
}
102+
pos
103+
}
78104
}

0 commit comments

Comments
 (0)