@@ -6,15 +6,12 @@ redirects:
6
6
title : ' Binary Search'
7
7
author : Darren Yao, Abutalib Namazov, Andrew Wang, Qi Wang, Dustin Miao
8
8
prerequisites :
9
- - greedy-sorting
9
+ - binary-search-sorted-array
10
10
description :
11
- ' Binary searching on arbitrary monotonic functions and built-in functions for
12
- binary search.'
11
+ ' Binary searching on arbitrary monotonic functions.'
13
12
frequency : 3
14
13
---
15
14
16
- <!-- process numbers from left to right, keep track of the last element of each block and use binary search of lower_bound to find which block the current numbers belongs -->
17
-
18
15
## Introduction
19
16
20
17
<Resources >
@@ -57,13 +54,14 @@ frequency: 3
57
54
58
55
<YouTube id = " GU7DpgHINWQ" />
59
56
60
- When we binary search on an answer , we start with a search space of size $N$
57
+ When we binary search, we start with a search space of size $N$
61
58
which we know the answer lies in. Then each iteration of the binary search cuts
62
59
the search space in half, so the algorithm tests $\mathcal{ O } (\log N)$ values.
63
60
This is efficient and much better than testing each possible value in the search
64
61
space.
65
62
66
- ## Binary Searching on Monotonic Functions
63
+
64
+ ## Binary Search on Monotonic Functions
67
65
68
66
Let's say we have a boolean function ` f(x) ` . Usually, in such problems, we want
69
67
to find the maximum or minimum value of $x$ such that ` f(x) ` is true. Similarly
@@ -812,311 +810,6 @@ The first version of `firstTrue` won't work if `hi-lo` initially exceeds
812
810
` INT_MAX ` at any point during execution. If this is an issue, use ` long long ` s
813
811
instead of ` int ` s.
814
812
815
- ## Library Functions For Binary Search
816
-
817
- <LanguageSection>
818
-
819
- <CPPSection>
820
-
821
- <Resources>
822
- <Resource
823
- source="CPP"
824
- url="http://www.cplusplus.com/reference/algorithm/lower_bound/"
825
- title="lower_bound, upper_bound"
826
- starred
827
- >
828
- with examples
829
- </Resource>
830
- </Resources>
831
-
832
- </CPPSection>
833
-
834
- <JavaSection>
835
-
836
- <Resources>
837
- <Resource
838
- source="JAVA"
839
- url="https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#binarySearch(int[],%20int)"
840
- title="Arrays.binarySearch"
841
- />
842
- <Resource
843
- source="JAVA"
844
- url="https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#binarySearch(java.util.List,%20T)"
845
- title="Collections.binarySearch"
846
- />
847
- </Resources>
848
-
849
- </JavaSection>
850
-
851
- <PySection>
852
-
853
- <Resources>
854
- <Resource
855
- source="Python"
856
- url="https://docs.python.org/3/library/bisect.html"
857
- title="Array bisection algorithm"
858
- />
859
- <Resource
860
- source="GFG"
861
- url="https://www.geeksforgeeks.org/binary-search-bisect-in-python/"
862
- title="Binary Search (bisect) in Python"
863
- />
864
- </Resources>
865
-
866
- </PySection>
867
-
868
- </LanguageSection>
869
-
870
- ### Example - Counting Haybales
871
-
872
- <FocusProblem problem="count" />
873
-
874
- As each of the points are in the range $0 \l dots 1\, 000\, 000\, 000$, storing
875
- locations of haybales in a boolean array and then taking prefix sums of that
876
- would take too much time and memory.
877
-
878
- Instead, let's place all of the locations of the haybales into a list and sort
879
- it. Now we can use binary search to count the number of cows in any range
880
- $[A,B]$ in $\m athcal{O}(\l og N)$ time.
881
-
882
- ### With Built-in Function
883
-
884
- <LanguageSection>
885
-
886
- <CPPSection>
887
-
888
- We can use the the built-in
889
- [ ` lower_bound ` ](https://en.cppreference.com/w/cpp/algorithm/lower_bound) and
890
- [ ` upper_bound ` ](https://en.cppreference.com/w/cpp/algorithm/upper_bound)
891
- functions.
892
-
893
- ` ` ` cpp
894
- #include <bits /stdc ++.h >
895
- using namespace std ;
896
-
897
- void setIO (string name = " " ) { // name is nonempty for USACO file I/O
898
- ios_base: : sync_with_stdio (0 );
899
- cin .tie (0 ); // see Fast Input & Output
900
- // alternatively, cin.tie(0)->sync_with_stdio(0);
901
- if (!name.empty()) {
902
- freopen ((name + " .in" ).c_str (), " r" , stdin ); // see Input & Output
903
- freopen ((name + " .out" ).c_str (), " w" , stdout );
904
- }
905
- }
906
-
907
- int main () {
908
- setIO(" haybales" );
909
- int bale_num;
910
- int query_num;
911
- cin >> bale_num >> query_num;
912
- vector <int > bales(bale_num );
913
- for (int i = 0 ; i < bale_num ; i ++) { cin >> bales [i ]; }
914
-
915
- sort(begin (bales ), end(bales ));
916
- for (int i = 0 ; i < query_num ; i ++) {
917
- int q_start ;
918
- int q_end ;
919
- cin >> q_start >> q_end ;
920
- cout << upper_bound (begin (bales ), end (bales ), q_end ) -
921
- lower_bound (begin (bales ), end (bales ), q_start )
922
- << " \n " ;
923
- }
924
- }
925
- ` ` `
926
-
927
- </CPPSection>
928
- <JavaSection>
929
-
930
- We can use the builtin
931
- [ ` Arrays .binarySearch ` ](<https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#binarySearch(int[],%20int)>)
932
- function.
933
-
934
- ` ` ` java
935
- import java .io .*;
936
- import java .util .*;
937
-
938
- public class Haybales {
939
- public static void main(String [] args ) throws IOException {
940
- BufferedReader br = new BufferedReader (new FileReader (new File (" haybales.in" )));
941
- PrintWriter out = new PrintWriter (" haybales.out" );
942
- StringTokenizer st = new StringTokenizer (br .readLine ());
943
-
944
- int baleNum = Integer .parseInt (st .nextToken ());
945
- int queryNum = Integer .parseInt (st .nextToken ());
946
- int [] bales = new int [baleNum ];
947
- st = new StringTokenizer (br .readLine ());
948
- for (int i = 0 ; i < baleNum ; i ++ ) {
949
- bales [i ] = Integer .parseInt (st .nextToken ());
950
- }
951
-
952
- Arrays .sort (bales );
953
- for (int i = 0 ; i < queryNum ; i ++ ) {
954
- st = new StringTokenizer (br .readLine ());
955
- int start = Integer .parseInt (st .nextToken ());
956
- int end = Integer .parseInt (st .nextToken ());
957
-
958
- // Get the left-est bale that's still in the interval
959
- int bi = Arrays .binarySearch (bales , start );
960
- if (bi < 0 ) { bi = Math .abs (bi + 1 ); }
961
-
962
- // And also get the right-est bale that's still in the interval
963
- int ti = Arrays .binarySearch (bales , end );
964
- if (ti < 0 ) { ti = Math .abs (ti + 2 ); }
965
- out .println (ti - bi + 1 );
966
- }
967
- out .close ();
968
- }
969
- }
970
- ` ` `
971
-
972
- </JavaSection>
973
- <PySection>
974
-
975
- We can use the builtin
976
- [ ` bisect .bisect ` ](https://docs.python.org/3/library/bisect.html#bisect.bisect)
977
- function.
978
-
979
- ` ` ` py
980
- from bisect import bisect
981
-
982
- inp = open (" haybales.in" , " r" )
983
- out = open (" haybales.out" , " w" )
984
-
985
- bale_num , query_num = map (int , inp.readline().split ())
986
- bales = sorted (list (map (int , inp.readline().split ())))
987
- for _ in range (query_num ):
988
- start , end = map (int , inp.readline().split ())
989
- print (bisect (bales , end ) - bisect (bales , start - 1), file =out )
990
- ` ` `
991
-
992
- </PySection>
993
- </LanguageSection>
994
-
995
- ### Without Using Built-in Functions
996
-
997
- <LanguageSection>
998
- <CPPSection>
999
-
1000
- ` ` ` cpp
1001
- #include <bits /stdc ++.h >
1002
- using namespace std ;
1003
-
1004
- void setIO (string name = " " ) { // name is nonempty for USACO file I/O
1005
- ios_base: : sync_with_stdio (0 );
1006
- cin .tie (0 ); // see Fast Input & Output
1007
- // alternatively, cin.tie(0)->sync_with_stdio(0);
1008
- if (!name.empty()) {
1009
- freopen ((name + " .in" ).c_str (), " r" , stdin ); // see Input & Output
1010
- freopen ((name + " .out" ).c_str (), " w" , stdout );
1011
- }
1012
- }
1013
-
1014
- int main () {
1015
- setIO(" haybales" );
1016
- int bale_num;
1017
- int query_num;
1018
- cin >> bale_num >> query_num;
1019
- vector <int > bales(bale_num );
1020
- for (int &i : bales ) { cin >> i ; }
1021
-
1022
- sort(begin (bales ), end(bales ));
1023
- // Returns the number of elements that are at most x
1024
- auto atMost = [& ](int x ) {
1025
- int lo = 0 ;
1026
- int hi = bales .size ();
1027
- while (lo < hi ) {
1028
- int mid = (lo + hi ) / 2 ;
1029
- if (bales [mid ] <= x ) {
1030
- lo = mid + 1 ;
1031
- } else {
1032
- hi = mid ;
1033
- }
1034
- }
1035
- return lo;
1036
- };
1037
-
1038
- for (int i = 0 ; i < query_num ; ++i ) {
1039
- int q_start ;
1040
- int q_end ;
1041
- cin >> q_start >> q_end ;
1042
- cout << atMost (q_end ) - atMost (q_start - 1 ) << " \n " ;
1043
- }
1044
- }
1045
- ` ` `
1046
-
1047
- </CPPSection>
1048
- <JavaSection>
1049
-
1050
- ` ` ` java
1051
- import java .io .*;
1052
- import java .util .*;
1053
-
1054
- public class Haybales {
1055
- static int [] bales;
1056
- public static void main(String [] args ) throws IOException {
1057
- Kattio io = new Kattio (" haybales" );
1058
- int baleNum = io .nextInt ();
1059
- int queryNum = io .nextInt ();
1060
- bales = new int [baleNum ];
1061
- for (int i = 0 ; i < baleNum ; i ++ ) { bales [i ] = io .nextInt (); }
1062
- Arrays .sort (bales );
1063
-
1064
- for (int i = 0 ; i < queryNum ; ++ i ) {
1065
- int start = io .nextInt ();
1066
- int end = io .nextInt ();
1067
- io .println (atMost (end ) - atMost (start - 1 ));
1068
- }
1069
- io .close ();
1070
- }
1071
-
1072
- // Returns the number of elements that are at most x
1073
- public static int atMost(int x ) {
1074
- int lo = 0 ;
1075
- int hi = bales .length ;
1076
- while (lo < hi ) {
1077
- int mid = (lo + hi ) / 2 ;
1078
- if (bales [mid ] <= x ) {
1079
- lo = mid + 1 ;
1080
- } else {
1081
- hi = mid ;
1082
- }
1083
- }
1084
- return lo ;
1085
- }
1086
-
1087
- // CodeSnip{Kattio}
1088
- }
1089
- ` ` `
1090
-
1091
- </JavaSection>
1092
- <PySection>
1093
-
1094
- ` ` ` py
1095
- def at_most (x : int ) -> int :
1096
- lo = 0
1097
- hi = len (bales )
1098
- while lo < hi :
1099
- mid = (lo + hi ) // 2
1100
- if bales [mid ] <= x :
1101
- lo = mid + 1
1102
- else :
1103
- hi = mid
1104
- return lo
1105
-
1106
-
1107
- inp = open (" haybales.in" , " r" )
1108
- out = open (" haybales.out" , " w" )
1109
-
1110
- bale_num , query_num = map (int , inp.readline().split ())
1111
- bales = sorted (list (map (int , inp.readline().split ())))
1112
- for _ in range (query_num ):
1113
- start , end = map (int , inp.readline().split ())
1114
- print (at_most (end ) - at_most (start - 1 ), file =out )
1115
- ` ` `
1116
-
1117
- </PySection>
1118
-
1119
- </LanguageSection>
1120
813
1121
814
## Problems
1122
815
0 commit comments