Skip to main content

bsearch/
lib.rs

1//! # Rust :: Binary Search
2
3/// 153m Find Minimum in Rotated Sorted Array
4struct Sol153;
5
6impl Sol153 {
7    pub fn find_min(nums: Vec<i32>) -> i32 {
8        let (mut l, mut r) = (0, nums.len() - 1);
9        while l < r {
10            let m = l + ((r - l) >> 1);
11            match nums[m].cmp(&nums[r]) {
12                std::cmp::Ordering::Greater => l = m + 1,
13                _ => r = m,
14            }
15        }
16
17        nums[l]
18    }
19}
20
21/// 154h Find Minimum in Rotated Sorted Array II
22struct Sol154;
23
24impl Sol154 {
25    pub fn find_min(nums: Vec<i32>) -> i32 {
26        use std::cmp::Ordering::*;
27
28        let (mut l, mut r) = (0, nums.len() - 1);
29        while l < r {
30            let m = l + ((r - l) >> 1);
31            match nums[m].cmp(&nums[r]) {
32                Greater => l = m + 1,
33                Less => r = m,
34                _ => r -= 1,
35            }
36        }
37
38        nums[l]
39    }
40}
41
42/// 315h Count of Smaller Numbers After Self
43struct Sol315;
44
45impl Sol315 {
46    pub fn count_smaller(nums: Vec<i32>) -> Vec<i32> {
47        let mut data = vec![];
48        for (i, &n) in nums.iter().enumerate() {
49            data.push((n, i, 0usize));
50        }
51
52        let mut bfr = data.to_vec();
53
54        fn merge(
55            data: &mut Vec<(i32, usize, usize)>,
56            bfr: &mut Vec<(i32, usize, usize)>,
57            l: usize,
58            r: usize,
59        ) {
60            if l >= r {
61                return;
62            }
63
64            let m = l + ((r - l) >> 1);
65            merge(bfr, data, l, m);
66            merge(bfr, data, m + 1, r);
67
68            let mut p = l;
69            let mut left = l;
70            let mut right = m + 1;
71
72            let mut smaller = 0;
73            while left <= m && right <= r {
74                if bfr[left].0 <= bfr[right].0 {
75                    data[p] = bfr[left];
76                    data[p].2 += smaller;
77
78                    left += 1;
79                } else {
80                    smaller += 1;
81                    data[p] = bfr[right];
82
83                    right += 1;
84                }
85                p += 1;
86            }
87
88            while left <= m {
89                data[p] = bfr[left];
90                data[p].2 += smaller;
91
92                left += 1;
93                p += 1;
94            }
95            while right <= r {
96                data[p] = bfr[right];
97
98                right += 1;
99                p += 1;
100            }
101        }
102
103        let n = data.len();
104        merge(&mut data, &mut bfr, 0, n - 1);
105
106        println!("-> {:?}", data);
107
108        let mut rst = vec![0; data.len()];
109        for (_, i, smaller) in data {
110            rst[i] = smaller as i32;
111        }
112
113        rst
114    }
115
116    /// 1 <= N <= 10^5
117    /// -10^4 <= V_i <= 10^4
118    fn bit_count_smaller(nums: Vec<i32>) -> Vec<i32> {
119        struct BITree {
120            tree: Vec<i32>,
121        }
122
123        impl BITree {
124            fn new(size: usize) -> Self {
125                BITree {
126                    tree: vec![0; size],
127                }
128            }
129
130            fn update(&mut self, mut p: i32, value: i32) {
131                while p < self.tree.len() as i32 {
132                    self.tree[p as usize] += value;
133                    p |= p + 1;
134                }
135            }
136
137            fn query(&self, mut p: i32) -> i32 {
138                let mut v = 0;
139                while p >= 0 {
140                    v += self.tree[p as usize];
141                    p &= p + 1;
142                    p -= 1;
143                }
144                v
145            }
146        }
147
148        const MAX: i32 = 10_000;
149
150        let mut rst = vec![];
151
152        let mut fwt = BITree::new(2 * MAX as usize + 1);
153        for p in (0..nums.len()).rev() {
154            rst.push(fwt.query(nums[p] + MAX - 1));
155            fwt.update(nums[p] + MAX, 1);
156        }
157
158        rst.reverse();
159        println!(":: {:?}", rst);
160
161        rst
162    }
163}
164
165/// 611m Valid Triangle Number
166struct Sol611 {}
167
168impl Sol611 {
169    pub fn triangle_number(mut nums: Vec<i32>) -> i32 {
170        nums.sort_unstable();
171        println!("-> {nums:?}");
172
173        let lsearch = |from, target| {
174            let (mut l, mut r) = (from, nums.len());
175            while l < r {
176                let m = l + ((r - l) >> 1);
177                if nums[m] < target {
178                    l = m + 1;
179                } else {
180                    r = m;
181                }
182            }
183
184            l
185        };
186
187        nums.iter()
188            .enumerate()
189            .filter(|&(_, &n)| n > 0)
190            .map(|(i, &a)| {
191                nums.iter()
192                    .enumerate()
193                    .take(nums.len() - 1)
194                    .skip(i + 1)
195                    .map(|(j, &b)| lsearch(j + 1, a + b) - (j + 1))
196                    .sum::<usize>()
197            })
198            .sum::<usize>() as _
199    }
200}
201
202/// 704 Binary Search
203struct Sol704;
204
205impl Sol704 {
206    pub fn search(nums: Vec<i32>, target: i32) -> i32 {
207        use std::cmp::Ordering::*;
208
209        let (mut left, mut right) = (0, nums.len() as i32 - 1);
210        while left <= right {
211            let m = left + ((right - left) >> 1);
212            match nums[m as usize].cmp(&target) {
213                Equal => return m,
214                Greater => right = m - 1,
215                Less => left = m + 1,
216            }
217        }
218        -1
219    }
220}
221
222/// 793h Preimage Size of Factorial Zeroes Function
223struct Sol793 {}
224
225impl Sol793 {
226    pub fn preimage_size_fzf(k: i32) -> i32 {
227        let fzf = |mut n| {
228            let mut count = 0;
229            while n / 5 > 0 {
230                count += n / 5;
231                n /= 5;
232            }
233            count
234        };
235
236        let lsearch = |target| {
237            let (mut l, mut r) = (0, i64::MAX);
238            while l < r {
239                let m = l + ((r - l) >> 1);
240                if fzf(m) < target {
241                    l = m + 1;
242                } else {
243                    r = m;
244                }
245            }
246            l
247        };
248
249        (lsearch(k as i64 + 1) - lsearch(k as i64)) as _
250    }
251}
252
253/// 1498m Number of Subsequences That Satisfy the Give Sum Condition
254struct Sol1498 {}
255
256impl Sol1498 {
257    /// 1 <= N <= 10^5
258    /// 1 <= N_i, target <= 10^6
259    pub fn num_subseq(mut nums: Vec<i32>, target: i32) -> i32 {
260        const M: i64 = 1e9 as i64 + 7;
261
262        let mpower = |mut exponent| {
263            let mut mpower = 1;
264            let mut base = 2;
265            while exponent > 0 {
266                if exponent & 1 == 1 {
267                    mpower = (base * mpower) % M;
268                }
269                base = (base * base) % M;
270                exponent >>= 1;
271            }
272
273            mpower
274        };
275        let _ = mpower(0);
276
277        let mut powers = vec![1; nums.len()];
278        for x in 1..powers.len() {
279            powers[x] = (powers[x - 1] * 2) % M;
280        }
281
282        nums.sort_unstable();
283
284        let mut count = 0;
285        let (mut left, mut right) = (0, nums.len() - 1);
286        while left <= right {
287            if nums[left] + nums[right] <= target {
288                count = (count + powers[right - left]) % M;
289                left += 1;
290            } else {
291                if right == 0 {
292                    break;
293                }
294                right -= 1;
295            }
296        }
297
298        count as _
299    }
300}
301
302/// 2040h Kth Smallest Product of Two Sorted Arrays
303struct Sol2040 {}
304
305impl Sol2040 {
306    /// 1 <= N <= 5*10^4
307    /// -10^5 <= N_i <= 10^5
308    pub fn kth_smallest_product(nums1: Vec<i32>, nums2: Vec<i32>, k: i64) -> i64 {
309        let count_smaller = |v| {
310            let mut count = 0;
311            for &n in &nums1 {
312                let (mut l, mut r) = (0, nums2.len());
313                while l < r {
314                    let m = l + ((r - l) >> 1);
315                    let p = nums2[m] as i64 * n as i64;
316                    if n >= 0 && p <= v || n < 0 && p > v {
317                        l = m + 1;
318                    } else {
319                        r = m;
320                    }
321                }
322
323                count += if n >= 0 { l } else { nums2.len() - l } as i64;
324            }
325
326            count
327        };
328
329        let (mut l, mut r) = (-1e10 as i64, 1e10 as i64);
330        while l < r {
331            let m = l + ((r - l) >> 1);
332            println!("-> {l} {m} {r}");
333
334            if count_smaller(m) < k {
335                l = m + 1;
336            } else {
337                r = m;
338            }
339        }
340
341        println!(":: {l}");
342        l
343    }
344}
345
346/// 2071h Maximum Number of Tasks You Can Assign
347struct Sol2071;
348
349impl Sol2071 {
350    pub fn max_task_assign(tasks: Vec<i32>, workers: Vec<i32>, pills: i32, strength: i32) -> i32 {
351        let (mut tasks, mut workers) = (tasks, workers);
352
353        tasks.sort_unstable();
354        workers.sort_unstable();
355
356        fn check(tasks: &[i32], workers: &[i32], mut pills: i32, strength: i32) -> bool {
357            use std::collections::BTreeMap;
358
359            let mut q = BTreeMap::new();
360            for wkr in workers {
361                q.entry(wkr).and_modify(|f| *f += 1).or_insert(1);
362            }
363
364            for tsk in tasks.iter().rev() {
365                if let Some((&wkr, _)) = q.iter().next_back() {
366                    if wkr >= tsk {
367                        q.entry(wkr).and_modify(|f| *f -= 1);
368                        if q[wkr] == 0 {
369                            q.remove(wkr);
370                        }
371                    } else {
372                        if pills == 0 {
373                            return false;
374                        }
375
376                        if let Some((&wkr, _)) = q.range(tsk - strength..).next() {
377                            pills -= 1;
378
379                            q.entry(wkr).and_modify(|f| *f -= 1);
380                            if q[wkr] == 0 {
381                                q.remove(wkr);
382                            }
383                        } else {
384                            return false;
385                        }
386                    }
387                }
388            }
389
390            true
391        }
392
393        let (mut l, mut r) = (0, tasks.len().min(workers.len()));
394        while l < r {
395            let m = l + ((r - l + 1) >> 1);
396
397            if check(&tasks[..m], &workers[workers.len() - m..], pills, strength) {
398                l = m;
399            } else {
400                r = m - 1;
401            }
402        }
403
404        l as _
405    }
406}
407
408/// 2226m Maximum Candies Allocated to K Children
409struct Sol2226;
410
411impl Sol2226 {
412    /// 1 <= C_i <= 10^7
413    pub fn maximum_candies(candies: Vec<i32>, k: i64) -> i32 {
414        let possible = |m| -> bool {
415            if m == 0 {
416                return true;
417            }
418
419            let mut t = 0;
420            for c in &candies {
421                t += (c / m) as i64;
422            }
423            t >= k
424        };
425
426        let (mut l, mut r) = (0, 1e7 as i32);
427        while l <= r {
428            let m = l + ((r - l) >> 1);
429            println!("-> {:?}", (l, m, r));
430            if possible(m) {
431                l = m + 1;
432            } else {
433                r = m - 1;
434            }
435        }
436
437        println!(":: {}", r);
438        r
439    }
440}
441
442/// 2529 Maximum Count of Positive Integer and Negative Integer
443struct Sol2529;
444
445impl Sol2529 {
446    pub fn maximum_count(nums: Vec<i32>) -> i32 {
447        fn bsleft(nums: &[i32], t: i32) -> i32 {
448            let (mut l, mut r) = (0, nums.len() as i32);
449            while l < r {
450                let m = l + ((r - l) >> 1);
451                match nums[m as usize].cmp(&t) {
452                    std::cmp::Ordering::Less => l = m + 1,
453                    _ => r = m,
454                }
455            }
456            l
457        }
458
459        fn bsright(nums: &[i32], t: i32) -> i32 {
460            let (mut l, mut r) = (0, nums.len() as i32);
461            while l < r {
462                let m = l + ((r - l) >> 1);
463                match nums[m as usize].cmp(&t) {
464                    std::cmp::Ordering::Greater => r = m,
465                    _ => l = m + 1,
466                }
467            }
468            r
469        }
470
471        (nums.len() as i32 - bsright(&nums, 0)).max(bsleft(&nums, 0))
472    }
473}
474
475/// 2560m House Robber IV
476struct Sol2560;
477
478impl Sol2560 {
479    pub fn min_capability(nums: Vec<i32>, k: i32) -> i32 {
480        match (nums.iter().min(), nums.iter().max()) {
481            (Some(&(mut l)), Some(&(mut r))) => {
482                while l < r {
483                    let m = l + ((r - l) >> 1);
484
485                    let mut steals = 0;
486                    let mut p = 0;
487                    while p < nums.len() {
488                        if nums[p] <= m {
489                            steals += 1;
490                            p += 1;
491                        }
492                        p += 1;
493                    }
494
495                    if steals >= k {
496                        r = m;
497                    } else {
498                        l = m + 1;
499                    }
500                }
501                l
502            }
503            _ => 0,
504        }
505    }
506}
507
508/// 2563m Count the Number of Fair Pairs
509struct Sol2563;
510
511impl Sol2563 {
512    /// 1 <= N <= 10^5
513    /// -10^9 <= N_i, lower, upper <= 10^9
514    pub fn count_fair_pairs(nums: Vec<i32>, lower: i32, upper: i32) -> i64 {
515        let mut nums = nums;
516        nums.sort_unstable();
517
518        println!("** {:?}", nums);
519
520        fn bsearch(nums: &[i32], l: usize, target: i32) -> usize {
521            let (mut l, mut r) = (l, nums.len());
522            while l < r {
523                let m = l + ((r - l) >> 1);
524                if nums[m] < target {
525                    l = m + 1;
526                } else {
527                    r = m;
528                }
529            }
530
531            l
532        }
533
534        nums.iter().enumerate().fold(0, |count, (l, &n)| {
535            let r_low = bsearch(&nums, l, lower - n);
536            let r_up = bsearch(&nums, l, upper - n + 1);
537
538            count + r_up - r_low
539        }) as i64
540    }
541}
542
543/// 2594m Minimum Time to Repair Cars
544struct Sol2594;
545
546impl Sol2594 {
547    /// 1 <= Rank_i <= 100
548    /// 1 <= N <= 10^5
549    pub fn repair_cars(ranks: Vec<i32>, cars: i32) -> i64 {
550        let (mut l, mut r) = (
551            1,
552            match ranks.iter().min() {
553                Some(&r) => r as i64 * cars as i64 * cars as i64,
554                _ => i64::MAX,
555            },
556        );
557
558        while l <= r {
559            let m = l + ((r - l) >> 1);
560            println!("-> {:?}", (l, m, r));
561
562            let mut repairs = 0;
563            for &r in &ranks {
564                repairs += (m / r as i64).isqrt();
565            }
566
567            if repairs >= cars as i64 {
568                r = m - 1;
569            } else {
570                l = m + 1;
571            }
572        }
573
574        println!(":: {}", l);
575
576        l
577    }
578}
579
580/// 2616m Minimize the Maximum Difference of Pairs
581struct Sol2616 {}
582
583impl Sol2616 {
584    /// 1 <= N <= 10^5, 0 <= N_i <= 10^9
585    /// 0 <= p <= N/2
586    pub fn minimize_max(nums: Vec<i32>, p: i32) -> i32 {
587        let mut nums = nums;
588        nums.sort_unstable();
589
590        let count_pairs = |m| {
591            let mut count = 0;
592            let mut i = 0;
593            while i < nums.len() - 1 {
594                if nums[i + 1] - nums[i] <= m {
595                    count += 1;
596                    i += 1;
597                }
598                i += 1;
599            }
600
601            count
602        };
603
604        let (mut l, mut r) = (0, nums.last().unwrap() - nums[0]);
605        while l < r {
606            let m = l + ((r - l) >> 1);
607
608            println!("-> {l} {m} {r}");
609
610            if count_pairs(m) >= p {
611                r = m;
612            } else {
613                l = m + 1;
614            }
615        }
616
617        l
618    }
619}
620
621/// 3356m Zero Array Transformation II
622struct Sol3356;
623
624impl Sol3356 {
625    pub fn min_zero_array(nums: Vec<i32>, queries: Vec<Vec<i32>>) -> i32 {
626        let possible = |k| -> bool {
627            let mut diffs = vec![0; nums.len() + 1];
628
629            for i in 0..k {
630                let qry = &queries[i as usize];
631                diffs[qry[0] as usize] += qry[2];
632                diffs[qry[1] as usize + 1] -= qry[2]
633            }
634
635            let mut tsum = 0;
636            for (&n, &s) in nums.iter().zip(diffs.iter()) {
637                tsum += s;
638                if n > tsum {
639                    return false;
640                }
641            }
642
643            true
644        };
645
646        if !possible(queries.len() as i32) {
647            return -1;
648        }
649
650        let (mut l, mut r) = (0, queries.len() as i32);
651        while l <= r {
652            let m = l + ((r - l) >> 1);
653            if possible(m) {
654                r = m - 1;
655            } else {
656                l = m + 1;
657            }
658        }
659
660        l
661    }
662}
663
664/// 3508m Implement Router
665#[derive(Debug)]
666struct Router3508 {
667    fifo: std::collections::VecDeque<(i32, i32, i32)>,
668    pkts: std::collections::HashSet<(i32, i32, i32)>,
669    dsts: std::collections::HashMap<i32, std::collections::VecDeque<i32>>,
670}
671
672impl Router3508 {
673    /// 1 <= Src, Dst <= 2*10^5
674    /// 1 <= T, T_start <= T_end <= 10^9
675    fn new(memory_limit: i32) -> Self {
676        Router3508 {
677            fifo: std::collections::VecDeque::with_capacity(memory_limit as usize),
678            pkts: std::collections::HashSet::new(),
679            dsts: std::collections::HashMap::new(),
680        }
681    }
682
683    fn add_packet(&mut self, source: i32, destination: i32, timestamp: i32) -> bool {
684        if self.pkts.contains(&(source, destination, timestamp)) {
685            false
686        } else {
687            if self.fifo.len() == self.fifo.capacity() {
688                self.forward_packet();
689            }
690
691            self.fifo.push_back((source, destination, timestamp));
692            self.pkts.insert((source, destination, timestamp));
693
694            self.dsts
695                .entry(destination)
696                .and_modify(|v| v.push_back(timestamp))
697                .or_insert(std::collections::VecDeque::from([timestamp]));
698
699            true
700        }
701    }
702
703    fn forward_packet(&mut self) -> Vec<i32> {
704        self.fifo.pop_front().map_or(vec![], |pkt| {
705            self.pkts.remove(&pkt);
706            self.dsts.get_mut(&pkt.1).map(|vd| vd.pop_front());
707            vec![pkt.0, pkt.1, pkt.2]
708        })
709    }
710
711    fn get_count(&self, destination: i32, start_time: i32, end_time: i32) -> i32 {
712        if let Some(v) = self.dsts.get(&destination)
713            && !v.is_empty()
714        {
715            let (mut l, mut r) = (0, v.len());
716            while l < r {
717                let m = l + ((r - l) >> 1);
718                if v[m] < start_time {
719                    l = m + 1;
720                } else {
721                    r = m;
722                }
723            }
724
725            if l == v.len() {
726                return 0;
727            }
728
729            let left = l;
730
731            r = v.len();
732            while l < r {
733                let m = l + ((r - l) >> 1);
734                if v[m] > end_time {
735                    r = m;
736                } else {
737                    l = m + 1;
738                }
739            }
740
741            (r - left) as _
742        } else {
743            0
744        }
745    }
746}
747
748#[cfg(test)]
749mod tests;