Skip to content

Commit a8f3889

Browse files
authored
Merge pull request #5176 from cpinitiative/silver-sorting-reorg
reorg Silver sorting and searching modules, move some modules to Gold
2 parents 3c4cd6e + 914bff6 commit a8f3889

22 files changed

+791
-732
lines changed

content/3_Silver/Binary_Search.mdx

+5-312
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,12 @@ redirects:
66
title: 'Binary Search'
77
author: Darren Yao, Abutalib Namazov, Andrew Wang, Qi Wang, Dustin Miao
88
prerequisites:
9-
- greedy-sorting
9+
- binary-search-sorted-array
1010
description:
11-
'Binary searching on arbitrary monotonic functions and built-in functions for
12-
binary search.'
11+
'Binary searching on arbitrary monotonic functions.'
1312
frequency: 3
1413
---
1514

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-
1815
## Introduction
1916

2017
<Resources>
@@ -57,13 +54,14 @@ frequency: 3
5754

5855
<YouTube id="GU7DpgHINWQ" />
5956

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$
6158
which we know the answer lies in. Then each iteration of the binary search cuts
6259
the search space in half, so the algorithm tests $\mathcal{O}(\log N)$ values.
6360
This is efficient and much better than testing each possible value in the search
6461
space.
6562

66-
## Binary Searching on Monotonic Functions
63+
64+
## Binary Search on Monotonic Functions
6765

6866
Let's say we have a boolean function `f(x)`. Usually, in such problems, we want
6967
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
812810
`INT_MAX` at any point during execution. If this is an issue, use `long long`s
813811
instead of `int`s.
814812
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 \ldots 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 $\mathcal{O}(\log 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>
1120813
1121814
## Problems
1122815

content/3_Silver/Binary_Search.problems.json

+12-26
Original file line numberDiff line numberDiff line change
@@ -116,33 +116,7 @@
116116
}
117117
}
118118
],
119-
"count": [
120-
{
121-
"uniqueId": "usaco-666",
122-
"name": "Counting Haybales",
123-
"url": "http://www.usaco.org/index.php?page=viewproblem2&cpid=666",
124-
"source": "Silver",
125-
"difficulty": "Easy",
126-
"isStarred": false,
127-
"tags": ["Binary Search"],
128-
"solutionMetadata": {
129-
"kind": "internal"
130-
}
131-
}
132-
],
133119
"general": [
134-
{
135-
"uniqueId": "cf-702C",
136-
"name": "Cellular Network",
137-
"url": "https://codeforces.com/contest/702/problem/C",
138-
"source": "CF",
139-
"difficulty": "Easy",
140-
"isStarred": false,
141-
"tags": ["Binary Search"],
142-
"solutionMetadata": {
143-
"kind": "internal"
144-
}
145-
},
146120
{
147121
"uniqueId": "cses-1620",
148122
"name": "Factory Machines",
@@ -179,6 +153,18 @@
179153
"kind": "internal"
180154
}
181155
},
156+
{
157+
"uniqueId": "cf-862E",
158+
"name": "Mahmoud & Ehab & Function",
159+
"url": "https://codeforces.com/contest/862/problem/E",
160+
"source": "CF",
161+
"difficulty": "Normal",
162+
"isStarred": false,
163+
"tags": ["Binary Search"],
164+
"solutionMetadata": {
165+
"kind": "internal"
166+
}
167+
},
182168
{
183169
"uniqueId": "cc-TRPTSTIC",
184170
"name": "TripTastic",

0 commit comments

Comments
 (0)