1
+ use std:: collections:: HashMap ;
2
+
3
+ struct MajorityChecker {
4
+ arr : Vec < i32 > ,
5
+ threshold : i32 ,
6
+ maybe : Vec < i32 > ,
7
+ sum : Vec < Vec < i32 > > ,
8
+ }
9
+
10
+ impl MajorityChecker {
11
+ fn new ( arr : Vec < i32 > ) -> Self {
12
+ let n = arr. len ( ) ;
13
+ let threshold = ( ( 2 * n) as f64 ) . sqrt ( ) as i32 ;
14
+ let mut hash = HashMap :: new ( ) ;
15
+ for & v in & arr {
16
+ * hash. entry ( v) . or_insert ( 0 ) += 1 ;
17
+ }
18
+ let mut maybe = vec ! [ ] ;
19
+ let mut sum = vec ! [ ] ;
20
+ for ( & k, & v) in hash. iter ( ) {
21
+ if v > threshold {
22
+ maybe. push ( k) ;
23
+ let mut t = vec ! [ 0 ; n+1 ] ;
24
+ for i in 0 ..n {
25
+ if arr[ i] == k {
26
+ t[ i+1 ] = t[ i] +1 ;
27
+ } else {
28
+ t[ i+1 ] = t[ i] ;
29
+ }
30
+ }
31
+ sum. push ( t) ;
32
+ }
33
+ }
34
+ Self {
35
+ arr,
36
+ threshold,
37
+ maybe,
38
+ sum,
39
+ }
40
+ }
41
+
42
+ fn query ( & self , left : i32 , right : i32 , threshold : i32 ) -> i32 {
43
+ let s = right-left+1 ;
44
+ if s <= self . threshold {
45
+ return self . count ( left, right, threshold) ;
46
+ }
47
+ let l = left as usize ;
48
+ let r = right as usize ;
49
+ for ( i, & v) in self . maybe . iter ( ) . enumerate ( ) {
50
+ if self . sum [ i] [ r+1 ] -self . sum [ i] [ l] >= threshold {
51
+ return v;
52
+ }
53
+ }
54
+ -1
55
+ }
56
+ fn count ( & self , left : i32 , right : i32 , threshold : i32 ) -> i32 {
57
+ let mut i = left as usize ;
58
+ let mut acc = 0 ;
59
+ let r = right as usize ;
60
+ let mut t = -1 ;
61
+ while i <= r {
62
+ if acc == 0 {
63
+ t = self . arr [ i] ;
64
+ acc += 1 ;
65
+ i+=1 ;
66
+ continue ;
67
+ }
68
+ if self . arr [ i] == t {
69
+ acc+=1 ;
70
+ } else {
71
+ acc-=1 ;
72
+ }
73
+ i+=1 ;
74
+ }
75
+ if acc == 0 {
76
+ return -1 ;
77
+ }
78
+ if ( left..=right) . into_iter ( ) . filter ( |& i| self . arr [ i as usize ] ==t) . count ( ) as i32 >= threshold {
79
+ t
80
+ } else {
81
+ -1
82
+ }
83
+ }
84
+ }
85
+
86
+ struct TreeChecker {
87
+ t : Option < Box < SegmentTree > > ,
88
+ pos : HashMap < i32 , Vec < usize > > ,
89
+ n : i32 ,
90
+ }
91
+
92
+ struct SegmentTree {
93
+ lch : Option < Box < SegmentTree > > ,
94
+ rch : Option < Box < SegmentTree > > ,
95
+ val : i32 ,
96
+ count : i32 ,
97
+ }
98
+
99
+ impl SegmentTree {
100
+ fn new ( arr : & Vec < i32 > , l : i32 , r : i32 ) -> Option < Box < Self > > {
101
+ if l == r {
102
+ return Some ( Box :: new ( SegmentTree {
103
+ lch : None ,
104
+ rch : None ,
105
+ val : arr[ l as usize ] ,
106
+ count : 1 ,
107
+ } ) ) ;
108
+ }
109
+ let m = ( l+r) /2 ;
110
+ let lch = Self :: new ( arr, l, m) ;
111
+ let rch = Self :: new ( arr, m+1 , r) ;
112
+ let ( lv, lc) = {
113
+ let p = lch. as_ref ( ) . unwrap ( ) ;
114
+ ( p. val , p. count )
115
+ } ;
116
+ let ( rv, rc) = {
117
+ let p = rch. as_ref ( ) . unwrap ( ) ;
118
+ ( p. val , p. count )
119
+ } ;
120
+ if lv == rv {
121
+ Some ( Box :: new ( SegmentTree {
122
+ lch,
123
+ rch,
124
+ val : lv,
125
+ count : lc+rc,
126
+ } ) )
127
+ } else {
128
+ if lc >= rc {
129
+ Some ( Box :: new ( SegmentTree {
130
+ lch,
131
+ rch,
132
+ val : lv,
133
+ count : lc-rc,
134
+ } ) )
135
+ } else {
136
+ Some ( Box :: new ( SegmentTree {
137
+ lch,
138
+ rch,
139
+ val : rv,
140
+ count : rc-lc,
141
+ } ) )
142
+ }
143
+ }
144
+ }
145
+ fn query ( & self , l : i32 , r : i32 , left : i32 , right : i32 ) -> ( i32 , i32 ) {
146
+ if l == left && r == right {
147
+ return ( self . val , self . count ) ;
148
+ }
149
+ let m = ( l+r) /2 ;
150
+ if right <= m {
151
+ self . lch . as_ref ( ) . unwrap ( ) . query ( l, m, left, right)
152
+ } else if left > m {
153
+ self . rch . as_ref ( ) . unwrap ( ) . query ( m+1 , r, left, right)
154
+ } else {
155
+ let ( lv, lc) = self . lch . as_ref ( ) . unwrap ( ) . query ( l, m, left, m) ;
156
+ let ( rv, rc) = self . rch . as_ref ( ) . unwrap ( ) . query ( m+1 , r, m+1 , right) ;
157
+ if lc >= rc {
158
+ ( lv, lc)
159
+ } else {
160
+ ( rv, rc)
161
+ }
162
+ }
163
+ }
164
+ }
165
+
166
+ impl TreeChecker {
167
+ fn new ( arr : Vec < i32 > ) -> Self {
168
+ let t = SegmentTree :: new ( & arr, 0 , arr. len ( ) as i32 -1 ) ;
169
+ let mut pos = HashMap :: new ( ) ;
170
+ for ( i, & v) in arr. iter ( ) . enumerate ( ) {
171
+ pos. entry ( v) . or_insert ( vec ! [ ] ) . push ( i) ;
172
+ }
173
+ Self {
174
+ t,
175
+ pos,
176
+ n : arr. len ( ) as i32 -1 ,
177
+ }
178
+ }
179
+ fn query ( & self , left : i32 , right : i32 , threshold : i32 ) -> i32 {
180
+ let ( v, _) = self . t . as_ref ( ) . unwrap ( ) . query ( 0 , self . n , left, right) ;
181
+ if let Some ( pos) = self . pos . get ( & v) {
182
+ match ( pos. binary_search ( & ( left as usize ) ) , pos. binary_search ( & ( right as usize ) ) ) {
183
+ ( Err ( a) , Err ( b) ) => {
184
+ if b-a >= threshold as usize {
185
+ return v;
186
+ }
187
+ } ,
188
+ ( Ok ( a) , Ok ( b) ) => {
189
+ if b-a+1 >= threshold as usize {
190
+ return v;
191
+ }
192
+ } ,
193
+ ( Err ( a) , Ok ( b) ) => {
194
+ if b-a+1 >= threshold as usize {
195
+ return v;
196
+ }
197
+ } ,
198
+ ( Ok ( a) , Err ( b) ) => {
199
+ if b-a >= threshold as usize {
200
+ return v;
201
+ }
202
+ }
203
+ }
204
+ }
205
+ -1
206
+ }
207
+ }
208
+
209
+ #[ cfg( test) ]
210
+ mod tests {
211
+ use super :: MajorityChecker ;
212
+ use super :: TreeChecker ;
213
+
214
+ #[ test]
215
+ fn test_sqrt ( ) {
216
+ let mut t = MajorityChecker :: new ( vec ! [ 1 , 1 , 2 , 2 , 1 , 1 ] ) ;
217
+ let test_cases = vec ! [
218
+ ( 2 , 3 , 2 , 2 ) ,
219
+ ( 0 , 5 , 4 , 1 ) ,
220
+ ( 0 , 3 , 3 , -1 ) ,
221
+ ] ;
222
+ for ( l, r, threshold, expect) in test_cases {
223
+ assert_eq ! ( t. query( l, r, threshold) , expect, "l:{}, r:{}, threshold:{}" , l, r, threshold) ;
224
+ }
225
+ }
226
+ #[ test]
227
+ fn test_tree ( ) {
228
+ let mut t = TreeChecker :: new ( vec ! [ 1 , 1 , 2 , 2 , 1 , 1 ] ) ;
229
+ let test_cases = vec ! [
230
+ ( 0 , 5 , 4 , 1 ) ,
231
+ ( 2 , 3 , 2 , 2 ) ,
232
+ ( 0 , 3 , 3 , -1 ) ,
233
+ ] ;
234
+ for ( l, r, threshold, expect) in test_cases {
235
+ assert_eq ! ( t. query( l, r, threshold) , expect, "l:{}, r:{}, threshold:{}" , l, r, threshold) ;
236
+ }
237
+ }
238
+ }
0 commit comments