Skip to content

Commit e58c615

Browse files
Binary trie (#36)
* add binary trie * small fix * udpate binary trie template * binary trie without template :) * clippy
1 parent 343a072 commit e58c615

File tree

5 files changed

+145
-9
lines changed

5 files changed

+145
-9
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ edition = "2024"
1010
[dependencies]
1111
proconio = "0.4.5"
1212

13+
[[example]]
14+
name = "binary_trie"
15+
path = "examples/data_structures/binary_trie.rs"
16+
1317
[[example]]
1418
name = "dsu_aizu"
1519
path = "examples/data_structures/dsu_aizu.rs"
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// verification-helper: PROBLEM https://judge.yosupo.jp/problem/set_xor_min
2+
3+
use proconio::input;
4+
use programming_team_code_rust::data_structures::binary_trie::BinaryTrie;
5+
6+
fn main() {
7+
input! {
8+
q: usize,
9+
}
10+
11+
let mut trie = BinaryTrie::default();
12+
for _ in 0..q {
13+
input! {
14+
t: u8,
15+
x: usize,
16+
}
17+
18+
match t {
19+
0 => {
20+
if trie.count(x) == 0 {
21+
trie.update(x, 1);
22+
}
23+
}
24+
1 => {
25+
if trie.count(x) == 1 {
26+
trie.update(x, -1);
27+
}
28+
}
29+
2 => {
30+
println!("{}", trie.min_xor(x));
31+
}
32+
_ => unreachable!(),
33+
}
34+
}
35+
}

src/data_structures/binary_trie.rs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//! # Binary Trie which can be used as a multiset of integers
2+
3+
#[derive(Default)]
4+
struct Node {
5+
next: [Option<usize>; 2],
6+
sub_sz: isize,
7+
}
8+
9+
/// # Example
10+
/// ```
11+
/// use programming_team_code_rust::data_structures::binary_trie::BinaryTrie;
12+
///
13+
/// let mut trie = BinaryTrie::default();
14+
/// trie.update(1, 1);
15+
/// trie.update(2, 1);
16+
/// trie.update(3, 1);
17+
/// trie.update(2, -1);
18+
/// assert_eq!(trie.count(2), 0);
19+
/// assert_eq!(trie.count(3), 1);
20+
/// assert_eq!(trie.count(4), 0);
21+
/// assert_eq!(trie.min_xor(0), 1);
22+
/// assert_eq!(trie.min_xor(1), 0);
23+
/// assert_eq!(trie.min_xor(2), 1);
24+
/// assert_eq!(trie.min_xor(3), 0);
25+
/// assert_eq!(trie.min_xor(4), 5);
26+
/// ```
27+
pub struct BinaryTrie {
28+
t: Vec<Node>,
29+
}
30+
31+
impl Default for BinaryTrie {
32+
fn default() -> Self {
33+
BinaryTrie {
34+
t: vec![Node::default()],
35+
}
36+
}
37+
}
38+
39+
impl BinaryTrie {
40+
/// Change the number of occurrences of `num` by `delta`
41+
///
42+
/// # Complexity
43+
/// - Time: O(log(max_num))
44+
/// - Space: O(log(max_num))
45+
pub fn update(&mut self, num: usize, delta: isize) {
46+
let mut v = 0;
47+
for i in (0..usize::BITS).rev() {
48+
let bit = (num >> i) & 1;
49+
if self.t[v].next[bit].is_none() {
50+
self.t[v].next[bit] = Some(self.t.len());
51+
self.t.push(Node::default());
52+
}
53+
self.t[v].sub_sz += delta;
54+
v = self.t[v].next[bit].unwrap();
55+
}
56+
self.t[v].sub_sz += delta;
57+
}
58+
59+
/// Count the number of occurrences of `num`
60+
///
61+
/// # Complexity
62+
/// - Time: O(log(max_num))
63+
/// - Space: O(1)
64+
pub fn count(&self, num: usize) -> isize {
65+
let mut v = 0;
66+
for i in (0..usize::BITS).rev() {
67+
let bit = (num >> i) & 1;
68+
if self.t[v].next[bit].is_none() {
69+
return 0;
70+
}
71+
v = self.t[v].next[bit].unwrap();
72+
}
73+
self.t[v].sub_sz
74+
}
75+
76+
/// Find the minimum xor of `num` and any number in the trie
77+
///
78+
/// # Panics
79+
/// ```panic
80+
/// use programming_team_code_rust::data_structures::binary_trie::BinaryTrie;
81+
///
82+
/// let trie = BinaryTrie::default();
83+
/// trie.min_xor(0);
84+
/// ```
85+
///
86+
/// # Complexity
87+
/// - Time: O(log(max_num))
88+
/// - Space: O(1)
89+
pub fn min_xor(&self, num: usize) -> usize {
90+
assert!(self.t.len() > 1);
91+
let mut v = 0;
92+
let mut ans = 0;
93+
for i in (0..usize::BITS).rev() {
94+
let bit = (num >> i) & 1;
95+
if self.t[v].next[bit].is_some() && self.t[self.t[v].next[bit].unwrap()].sub_sz > 0 {
96+
v = self.t[v].next[bit].unwrap();
97+
} else {
98+
ans |= 1 << i;
99+
v = self.t[v].next[bit ^ 1].unwrap();
100+
}
101+
}
102+
ans
103+
}
104+
}

src/data_structures/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! # Data Structures
2+
pub mod binary_trie;
23
pub mod dsu;
34
pub mod fenwick;
45
pub mod rmq;

src/data_structures/trie.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,12 @@
33
const ALPHABET_SIZE: usize = 26;
44
const FIRST_CHAR: char = 'A';
55

6+
#[derive(Default)]
67
struct Node {
78
next: [Option<usize>; ALPHABET_SIZE],
89
cnt_words: usize,
910
}
1011

11-
impl Default for Node {
12-
fn default() -> Self {
13-
Node {
14-
next: [None; ALPHABET_SIZE],
15-
cnt_words: 0,
16-
}
17-
}
18-
}
19-
2012
/// # Example
2113
/// ```
2214
/// use programming_team_code_rust::data_structures::trie::Trie;

0 commit comments

Comments
 (0)