7
7
///
8
8
/// - modify(l, r, f) replaces a_i (l <= i <= r) by f(a_i) for a homomorphism f
9
9
/// - query(l, r) returns the aggregate a_l + a_{l+1} + ... + a_r
10
- ///
11
- /// To customize, simply change the commented lines.
12
- /// In this example, we chose to support range sum queries and range constant
13
- /// assignments. Since constant assignment f_c(a) = c is not a homomorphism over
14
- /// integers, we have to augment the monoid type, using the 2D vector (a_i, 1)
15
- /// instead of a_i. You may check that f_c((a, s)) = (c*s, s) is a homomorphism.
16
- pub struct ArqTree {
17
- d : Vec < Option < i64 > > ,
18
- t : Vec < i64 > ,
19
- s : Vec < i64 > ,
10
+ pub struct ArqTree < T : ArqSpec > {
11
+ d : Vec < Option < T :: H > > ,
12
+ t : Vec < T :: M > ,
20
13
}
21
14
22
- impl ArqTree {
23
- /// Initializes a sequence of identity elements.
24
- pub fn new ( size : usize ) -> Self {
25
- let mut s = vec ! [ 1 ; 2 * size] ;
15
+ impl < T : ArqSpec > ArqTree < T >
16
+ where
17
+ T :: H : Clone ,
18
+ {
19
+ /// Initializes a static balanced tree on top of the given sequence.
20
+ pub fn new ( mut init : Vec < T :: M > ) -> Self {
21
+ let size = init. len ( ) ;
22
+ let mut t = ( 0 ..size) . map ( |_| T :: identity ( ) ) . collect :: < Vec < _ > > ( ) ;
23
+ t. append ( & mut init) ;
26
24
for i in ( 0 ..size) . rev ( ) {
27
- s [ i] = s [ i << 1 ] + s [ i << 1 | 1 ] ;
25
+ t [ i] = T :: op ( & t [ i << 1 ] , & t [ i << 1 | 1 ] ) ;
28
26
}
29
27
Self {
30
- d : vec ! [ None ; size] ,
31
- t : vec ! [ 0 ; 2 * size] , // monoid identity
32
- s : s,
28
+ d : ( 0 ..size) . map ( |_| None ) . collect ( ) ,
29
+ t : t,
33
30
}
34
31
}
35
32
36
- fn apply ( & mut self , p : usize , f : i64 ) {
37
- self . t [ p] = f * self . s [ p] ; // hom application
33
+ fn apply ( & mut self , p : usize , f : & T :: H ) {
34
+ self . t [ p] = T :: apply ( f , & self . t [ p] ) ; // hom application
38
35
if p < self . d . len ( ) {
39
- self . d [ p] = Some ( f) ; // hom composition
36
+ let h = if let Some ( ref g) = self . d [ p] {
37
+ T :: compose ( f, g)
38
+ } else {
39
+ f. clone ( )
40
+ } ;
41
+ self . d [ p] = Some ( h) ;
40
42
}
41
43
}
42
44
43
45
fn push ( & mut self , p : usize ) {
44
46
for s in ( 1 ..32 ) . rev ( ) {
45
47
let i = p >> s;
46
- if let Some ( f) = self . d [ i] {
48
+ if let Some ( ref f) = self . d [ i] . take ( ) {
47
49
self . apply ( i << 1 , f) ;
48
50
self . apply ( i << 1 | 1 , f) ;
49
- self . d [ i] = None ;
50
51
}
51
52
}
52
53
}
53
54
54
55
fn pull ( & mut self , mut p : usize ) {
55
56
while p > 1 {
56
57
p >>= 1 ;
57
- if self . d [ p] == None {
58
- self . t [ p] = self . t [ p << 1 ] + self . t [ p << 1 | 1 ] ; // monoid op
58
+ if self . d [ p] . is_none ( ) {
59
+ self . t [ p] = T :: op ( & self . t [ p << 1 ] , & self . t [ p << 1 | 1 ] ) ; // monoid op
59
60
}
60
61
}
61
62
}
62
63
63
64
/// Performs the homomorphism f on all entries from l to r, inclusive.
64
- pub fn modify ( & mut self , mut l : usize , mut r : usize , f : i64 ) {
65
+ pub fn modify ( & mut self , mut l : usize , mut r : usize , f : & T :: H ) {
65
66
l += self . d . len ( ) ;
66
67
r += self . d . len ( ) ;
67
68
let ( l0, r0) = ( l, r) ;
@@ -84,19 +85,19 @@ impl ArqTree {
84
85
}
85
86
86
87
/// Returns the aggregate range query on all entries from l to r, inclusive.
87
- pub fn query ( & mut self , mut l : usize , mut r : usize ) -> i64 {
88
+ pub fn query ( & mut self , mut l : usize , mut r : usize ) -> T :: M {
88
89
l += self . d . len ( ) ;
89
90
r += self . d . len ( ) ;
90
91
self . push ( l) ;
91
92
self . push ( r) ;
92
- let mut res = 0 ; // monoid identity
93
+ let mut res = T :: identity ( ) ; // monoid identity
93
94
while l <= r {
94
95
if l & 1 == 1 {
95
- res = res + self . t [ l] ; // monoid op
96
+ res = T :: op ( & res, & self . t [ l] ) ; // monoid op
96
97
l += 1 ;
97
98
}
98
99
if r & 1 == 0 {
99
- res = self . t [ r] + res; // monoid op
100
+ res = T :: op ( & self . t [ r] , & res) ; // monoid op
100
101
r -= 1 ;
101
102
}
102
103
l >>= 1 ;
@@ -106,17 +107,52 @@ impl ArqTree {
106
107
}
107
108
}
108
109
110
+ pub trait ArqSpec {
111
+ type H ;
112
+ type M ;
113
+ fn compose ( f : & Self :: H , g : & Self :: H ) -> Self :: H ;
114
+ fn apply ( f : & Self :: H , a : & Self :: M ) -> Self :: M ;
115
+ fn op ( a : & Self :: M , b : & Self :: M ) -> Self :: M ;
116
+ fn identity ( ) -> Self :: M ;
117
+ }
118
+
119
+ /// In this example, we chose to support range sum queries and range constant
120
+ /// assignments. Since constant assignment f_c(a) = c is not a homomorphism over
121
+ /// integers, we have to augment the monoid type, using the 2D vector (a_i, 1)
122
+ /// instead of a_i. You may check that f_c((a, s)) = (c*s, s) is a homomorphism.
123
+ pub struct AssignAdd ;
124
+
125
+ impl ArqSpec for AssignAdd {
126
+ type H = i64 ;
127
+ type M = ( i64 , i64 ) ;
128
+ fn compose ( f : & Self :: H , _: & Self :: H ) -> Self :: H {
129
+ * f
130
+ }
131
+ fn apply ( f : & Self :: H , a : & Self :: M ) -> Self :: M {
132
+ ( f * a. 1 , a. 1 )
133
+ }
134
+ fn op ( a : & Self :: M , b : & Self :: M ) -> Self :: M {
135
+ ( a. 0 + b. 0 , a. 1 + b. 1 )
136
+ }
137
+ fn identity ( ) -> Self :: M {
138
+ ( 0 , 0 )
139
+ }
140
+ }
141
+
142
+
109
143
#[ cfg( test) ]
110
144
mod test {
111
145
use super :: * ;
112
146
113
147
#[ test]
114
148
fn test_arq_tree ( ) {
115
- let mut arq = ArqTree :: new ( 10 ) ;
149
+ let mut arq = ArqTree :: < AssignAdd > :: new ( vec ! [ ( 0 , 1 ) ; 10 ] ) ;
150
+
151
+ assert_eq ! ( arq. query( 0 , 9 ) , ( 0 , 10 ) ) ;
116
152
117
- arq. modify ( 1 , 3 , 10 ) ;
118
- arq. modify ( 3 , 5 , 1 ) ;
153
+ arq. modify ( 1 , 3 , & 10 ) ;
154
+ arq. modify ( 3 , 5 , & 1 ) ;
119
155
120
- assert_eq ! ( arq. query( 0 , 9 ) , 23 ) ;
156
+ assert_eq ! ( arq. query( 0 , 9 ) , ( 23 , 10 ) ) ;
121
157
}
122
158
}
0 commit comments