@@ -2,21 +2,21 @@ use crate::util::iter::*;
2
2
use crate :: util:: parse:: * ;
3
3
use std:: ops:: { Index , IndexMut } ;
4
4
5
- #[ derive( Clone , Copy ) ]
5
+ #[ derive( Clone , Copy , Default ) ]
6
6
struct Node {
7
7
size : u16 ,
8
8
left : u16 ,
9
9
right : u16 ,
10
10
up : u16 ,
11
11
}
12
12
13
- struct Tree {
13
+ struct OrderStatisticTree {
14
14
root : u16 ,
15
- size : i64 ,
15
+ size : u16 ,
16
16
nodes : Vec < Node > ,
17
17
}
18
18
19
- impl Index < u16 > for Tree {
19
+ impl Index < u16 > for OrderStatisticTree {
20
20
type Output = Node ;
21
21
22
22
#[ inline]
@@ -25,27 +25,27 @@ impl Index<u16> for Tree {
25
25
}
26
26
}
27
27
28
- impl IndexMut < u16 > for Tree {
28
+ impl IndexMut < u16 > for OrderStatisticTree {
29
29
#[ inline]
30
30
fn index_mut ( & mut self , index : u16 ) -> & mut Self :: Output {
31
31
& mut self . nodes [ index as usize ]
32
32
}
33
33
}
34
34
35
- impl Tree {
36
- fn from ( input : & [ i64 ] ) -> Tree {
37
- let mut size = input. len ( ) ;
35
+ impl OrderStatisticTree {
36
+ fn from ( size : usize ) -> Self {
38
37
let mut start = 0 ;
39
38
let mut end = size;
39
+ let mut level = size;
40
40
41
- let mut remaining = None ;
42
41
let mut nodes = Vec :: with_capacity ( size * 2 ) ;
42
+ let mut remaining = None ;
43
43
44
44
let empty = u16:: MAX ;
45
- let leaf = Node { size : 1 , left : empty , right : empty , up : empty } ;
45
+ let leaf = Node { size : 1 , .. Default :: default ( ) } ;
46
46
nodes. resize ( size, leaf) ;
47
47
48
- while size > 0 {
48
+ while level > 0 {
49
49
let mut push = |left : usize , right : usize | {
50
50
let index = nodes. len ( ) as u16 ;
51
51
nodes[ left] . up = index;
@@ -59,7 +59,7 @@ impl Tree {
59
59
push ( left, right) ;
60
60
}
61
61
62
- if size % 2 == 1 {
62
+ if level % 2 == 1 {
63
63
if let Some ( right) = remaining {
64
64
remaining = None ;
65
65
push ( end - 1 , right) ;
@@ -70,13 +70,13 @@ impl Tree {
70
70
71
71
start = end;
72
72
end = nodes. len ( ) ;
73
- size = end - start;
73
+ level = end - start;
74
74
}
75
75
76
- Tree { root : ( end - 1 ) as u16 , size : ( input . len ( ) - 1 ) as i64 , nodes }
76
+ OrderStatisticTree { root : ( end - 1 ) as u16 , size : ( size - 1 ) as u16 , nodes }
77
77
}
78
78
79
- fn position ( & self , start : usize ) -> u16 {
79
+ fn position ( & self , start : usize ) -> usize {
80
80
let mut cur = start as u16 ;
81
81
let mut offset = 0 ;
82
82
@@ -89,12 +89,12 @@ impl Tree {
89
89
cur = next;
90
90
}
91
91
92
- offset
92
+ offset as usize
93
93
}
94
94
95
- fn value_at ( & self , start : u16 ) -> usize {
95
+ fn value_at ( & self , start : usize ) -> usize {
96
96
let mut cur = self . root ;
97
- let mut offset = start;
97
+ let mut offset = start as u16 ;
98
98
99
99
loop {
100
100
let Node { size, left, right, .. } = self [ cur] ;
@@ -114,71 +114,116 @@ impl Tree {
114
114
}
115
115
116
116
fn mix ( & mut self , start : usize , value : i64 ) {
117
- let start = start as u16 ;
118
- let mut cur = start;
119
- let mut offset = 0 ;
117
+ let mut delta_right = value. rem_euclid ( self . size as i64 ) as u16 ;
118
+ let mut delta_left = self . size - delta_right;
120
119
121
- while cur != self . root {
122
- let next = self [ cur] . up ;
123
- let Node { left, right, .. } = self [ next] ;
124
-
125
- if right == cur {
126
- offset += self [ left] . size ;
127
- } ;
128
- self [ next] . size -= 1 ;
129
- cur = next;
120
+ if delta_left == 0 || delta_right == 0 {
121
+ return ;
130
122
}
131
123
124
+ // Temporarily set our size to zero
125
+ let start = start as u16 ;
126
+ self [ start] . size = 0 ;
127
+
132
128
let parent = self [ start] . up ;
129
+ let mut dest = parent;
133
130
134
- if parent == self . root {
135
- if self [ self . root ] . left == start {
136
- self . root = self [ self . root ] . right ;
137
- } else {
138
- self . root = self [ self . root ] . left ;
131
+ // Go up
132
+ let ( left, right) = loop {
133
+ let Node { left, right, up, .. } = self [ dest] ;
134
+ let left_size = self [ left] . size ;
135
+ let right_size = self [ right] . size ;
136
+
137
+ if delta_left <= left_size || delta_right <= right_size {
138
+ break ( left, right) ;
139
139
}
140
- } else {
141
- let grand_parent = self [ parent] . up ;
142
- let next_parent =
143
- if self [ parent] . left == start { self [ parent] . right } else { self [ parent] . left } ;
144
- self [ next_parent] . up = grand_parent;
145
- if self [ grand_parent] . left == parent {
146
- self [ grand_parent] . left = next_parent;
140
+
141
+ if self [ up] . left == dest {
142
+ delta_right -= right_size;
143
+ delta_left += right_size;
147
144
} else {
148
- self [ grand_parent] . right = next_parent;
145
+ delta_right += left_size;
146
+ delta_left -= left_size;
149
147
}
150
- }
151
148
152
- cur = self . root ;
153
- offset = ( offset as i64 + value) . rem_euclid ( self . size ) as u16 ;
149
+ self [ dest] . size -= 1 ;
150
+ dest = up;
151
+ } ;
154
152
155
- loop {
156
- let Node { size, left, right, up } = self [ cur] ;
153
+ let ( left, right) = if delta_left <= self [ left] . size {
154
+ // Down left
155
+ dest = left;
157
156
158
- if size == 1 {
159
- self [ parent ] = Node { size : 2 , left : start , right : cur , up } ;
157
+ loop {
158
+ let Node { size, left, right, .. } = self [ dest ] ;
160
159
161
- self [ cur] . up = parent;
162
- self [ start] . up = parent;
160
+ if size == 1 {
161
+ break ( start, dest) ;
162
+ }
163
163
164
- if self [ up] . left == cur {
165
- self [ up] . left = parent;
164
+ self [ dest] . size += 1 ;
165
+ let right_size = self [ right] . size ;
166
+
167
+ if delta_left <= right_size {
168
+ dest = right;
166
169
} else {
167
- self [ up] . right = parent;
170
+ delta_left -= right_size;
171
+ dest = left;
168
172
}
173
+ }
174
+ } else {
175
+ // Down right
176
+ dest = right;
177
+
178
+ loop {
179
+ let Node { size, left, right, .. } = self [ dest] ;
180
+
181
+ if size == 1 {
182
+ break ( dest, start) ;
183
+ }
184
+
185
+ self [ dest] . size += 1 ;
186
+ let left_size = self [ left] . size ;
169
187
170
- break ;
188
+ if delta_right <= left_size {
189
+ dest = left;
190
+ } else {
191
+ delta_right -= left_size;
192
+ dest = right;
193
+ }
171
194
}
195
+ } ;
172
196
173
- self [ cur] . size += 1 ;
174
- let size = self [ left] . size ;
175
- if offset < size {
176
- cur = left;
197
+ // Remove node
198
+ let sibling =
199
+ if self [ parent] . left == start { self [ parent] . right } else { self [ parent] . left } ;
200
+
201
+ if parent == self . root {
202
+ self [ sibling] . size += 1 ;
203
+ self . root = sibling;
204
+ } else {
205
+ let grand_parent = self [ parent] . up ;
206
+ self [ sibling] . up = grand_parent;
207
+
208
+ if self [ grand_parent] . left == parent {
209
+ self [ grand_parent] . left = sibling;
177
210
} else {
178
- cur = right;
179
- offset -= size;
211
+ self [ grand_parent] . right = sibling;
180
212
}
181
213
}
214
+
215
+ // Insert node
216
+ let up = self [ dest] . up ;
217
+
218
+ if self [ up] . left == dest {
219
+ self [ up] . left = parent;
220
+ } else {
221
+ self [ up] . right = parent;
222
+ }
223
+
224
+ self [ parent] = Node { size : 2 , left, right, up } ;
225
+ self [ left] = Node { size : 1 , up : parent, ..Default :: default ( ) } ;
226
+ self [ right] = Node { size : 1 , up : parent, ..Default :: default ( ) } ;
182
227
}
183
228
}
184
229
@@ -195,7 +240,7 @@ pub fn part2(input: &[i64]) -> i64 {
195
240
}
196
241
197
242
fn decrypt ( input : & [ i64 ] , key : i64 , rounds : usize ) -> i64 {
198
- let mut tree = Tree :: from ( input) ;
243
+ let mut tree = OrderStatisticTree :: from ( input. len ( ) ) ;
199
244
200
245
for _ in 0 ..rounds {
201
246
for ( i, n) in input. iter ( ) . enumerate ( ) {
@@ -207,7 +252,7 @@ fn decrypt(input: &[i64], key: i64, rounds: usize) -> i64 {
207
252
let zeroth = tree. position ( start) ;
208
253
[ 1000 , 2000 , 3000 ]
209
254
. iter ( )
210
- . map ( |offset| tree. value_at ( ( zeroth + offset) % ( input. len ( ) as u16 ) ) )
255
+ . map ( |offset| tree. value_at ( ( zeroth + offset) % input. len ( ) ) )
211
256
. map ( |index| input[ index] * key)
212
257
. sum ( )
213
258
}
0 commit comments