Skip to content

Commit 4a52ed3

Browse files
authored
Merge pull request #394 from xirc/lib/binary-search
Add binary search library
2 parents 49e5a3c + 0635332 commit 4a52ed3

File tree

6 files changed

+115
-22
lines changed

6 files changed

+115
-22
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ This project contains my competitive programming library, examples, and solution
117117

118118
### [Utilities](/lib/cpalgo/util)
119119

120+
* [Binary Search](/lib/cpalgo/util/README.md#Binary-Search)
120121
* [Two Pointers](/lib/cpalgo/util/README.md#Two-Pointers)
121122
"しゃくとり法" in Japanese
122123
* [BigInt](/lib/cpalgo/util/README.md#BigInt)

atcoder/abc034/D/main.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
#include <bits/stdc++.h>
22

3+
inline long double binary_search_f(
4+
std::function<bool(long double)> const& predicate,
5+
long double ng,
6+
long double ok,
7+
const size_t N = 200
8+
) {
9+
assert(!predicate(ng) && predicate(ok));
10+
for (size_t i = 0; i < N; ++i) {
11+
auto m = (ok + ng) / 2;
12+
if (predicate(m)) ok = m;
13+
else ng = m;
14+
}
15+
return ok;
16+
}
17+
318
using namespace std;
419
using ll = int64_t;
520
using lf = long double;
@@ -23,6 +38,7 @@ bool pass(lf pth) {
2338
return u - 1e-8 > 0;
2439
}
2540

41+
2642
int main() {
2743
ios_base::sync_with_stdio(false);
2844
cin.tie(0); cout.tie(0);
@@ -34,15 +50,8 @@ int main() {
3450
}
3551

3652
lf ok = 0.0, ng = 200.0;
37-
for (int i = 0; i < 400; ++i) {
38-
lf m = (ok + ng) / 2.0;
39-
if (pass(m)) {
40-
ok = m;
41-
} else {
42-
ng = m;
43-
}
44-
}
45-
cout << fixed << setprecision(6) << ok << endl;
53+
auto ans = binary_search_f(pass, ng, ok, 400);
54+
cout << fixed << setprecision(6) << ans << endl;
4655

4756
return 0;
4857
}

atcoder/abc063/D/main.cpp

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
#include <bits/stdc++.h>
22

3+
inline int64_t binary_search(
4+
std::function<bool(int64_t)> const& predicate,
5+
int64_t ng,
6+
int64_t ok
7+
) {
8+
assert(!predicate(ng) && predicate(ok));
9+
while (abs(ok - ng) > 1) {
10+
auto m = (ok + ng) / 2;
11+
if (predicate(m)) ok = m;
12+
else ng = m;
13+
}
14+
return ok;
15+
}
16+
317
using namespace std;
4-
using ll = long long;
18+
using ll = int64_t;
519

620
int N, A, B;
721
vector<int> H;
822

9-
bool is_ok(const ll M) {
23+
bool satisfy(const ll M) {
1024
int mxh = *max_element(H.begin(), H.end());
1125
if (mxh / B < M) return true; // prevent an overflow
1226
assert(B * M <= mxh);
@@ -25,17 +39,8 @@ bool is_ok(const ll M) {
2539
}
2640

2741
ll solve() {
28-
ll low = 0, high = 1e15;
29-
assert(!is_ok(low) && is_ok(high));
30-
while (high - low > 1) {
31-
auto m = low + (high - low) / 2;
32-
if (is_ok(m)) {
33-
high = m;
34-
} else {
35-
low = m;
36-
}
37-
}
38-
return high;
42+
ll ng = 0, ok = 1e15;
43+
return binary_search(satisfy, ng, ok);
3944
}
4045

4146
int main() {

lib/cpalgo/util/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@
1414
- [単調増加 - AtCoder ABC038C](https://atcoder.jp/contests/abc038/tasks/abc038_c)
1515

1616

17+
## Binary Search
18+
*Binary Search* is an algorithm technique that reduces solution space by half at one iteration.
19+
Although Binary Search often is used in which we search a specific value in a given sorted array, it is not limited.
20+
We can use this technique in many problems. It's a pretty powerful technique.
21+
22+
[Binary Search (Integer) | C++ code](binary-search.hpp)
23+
[Binary Search (Double) | C++ code](binary-search_f.hpp)
24+
25+
### Challenges
26+
- [食塩水](https://atcoder.jp/contests/abc034/tasks/abc034_d)
27+
- [Widespread](https://atcoder.jp/contests/abc063/tasks/arc075_b)
28+
29+
1730
## Dice
1831
🚧WIP
1932

lib/cpalgo/util/binary_search.hpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#pragma once
2+
3+
#include <limits>
4+
#include <functional>
5+
#include <cassert>
6+
7+
8+
// Binary Search for an integer number
9+
//
10+
// Time: O(logN)
11+
// Space: O(1)
12+
//
13+
// See:
14+
// - https://qiita.com/drken/items/97e37dd6143e33a64c8c
15+
//
16+
// Verified:
17+
// - https://atcoder.jp/contests/abc063/tasks/arc075_b
18+
//
19+
inline int64_t binary_search(
20+
std::function<bool(int64_t)> const& predicate,
21+
int64_t ng,
22+
int64_t ok
23+
) {
24+
assert(!predicate(ng) && predicate(ok));
25+
while (abs(ok - ng) > 1) {
26+
auto m = (ok + ng) / 2;
27+
if (predicate(m)) ok = m;
28+
else ng = m;
29+
}
30+
return ok;
31+
}

lib/cpalgo/util/binary_search_f.hpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#pragma once
2+
3+
#include <limits>
4+
#include <functional>
5+
#include <cassert>
6+
7+
8+
// Binary Search for a floating point number
9+
//
10+
// Time: O(N)
11+
// Space: O(1)
12+
//
13+
// NOTE:
14+
// Use constant loop to avoid precision problems.
15+
// Every loop reduces solution space by half.
16+
// It would be better to pick a suitable loop count depending on a problem.
17+
//
18+
// Verified:
19+
// - https://atcoder.jp/contests/abc034/tasks/abc034_d
20+
//
21+
inline long double binary_search_f(
22+
std::function<bool(long double)> const& predicate,
23+
long double ng,
24+
long double ok,
25+
const size_t N = 200
26+
) {
27+
assert(!predicate(ng) && predicate(ok));
28+
for (size_t i = 0; i < N; ++i) {
29+
auto m = (ok + ng) / 2;
30+
if (predicate(m)) ok = m;
31+
else ng = m;
32+
}
33+
return ok;
34+
}

0 commit comments

Comments
 (0)