Khoá học C++ nâng cao
Bài học: Tìm Kiếm Nhị Phân Nâng Cao
🏆 +100 XP tiềm năng Thoát

Tìm Kiếm Nhị Phân Nâng Cao

2 khối nội dung 45 phút học tập MỞ BẢNG TRẮNG

Tìm Kiếm Nhị Phân Nâng Cao

Nội dung bài học

1. Khái niệm & bản chất của tìm kiếm nhị phân trong không gian nghiệm

Tìm kiếm nhị phân (Binary Search) không chỉ giới hạn ở việc tìm kiếm một phần tử trên mảng đã sắp xếp trong $\mathcal{O}(\log N)$, mà ở cấp độ thi đấu nâng cao, nó là một phương pháp tối ưu hóa tổng quát trên không gian hàm đơn điệu:

  • Chặt nhị phân kết quả (Binary Search on Answer): Chuyển đổi một bài toán tối ưu hóa khó ("Tìm giá trị $X$ nhỏ nhất/lớn nhất thỏa mãn điều kiện...") thành một chuỗi các bài toán kiểm tra tính khả thi dễ dàng ("Với giá trị $X$ cho trước, có thể đạt được mục tiêu hay không?") thông qua một hàm kiểm tra đơn điệu check(X).
  • Tìm kiếm nhị phân trên số thực (Real Binary Search): Tìm nghiệm của phương trình hoặc hàm số liên tục với độ chính xác tuyệt đối $\epsilon = 10^{-7}$.
  • Tìm kiếm tam phân (Ternary Search): Tìm điểm cực trị (cực đại/cực tiểu) của hàm số đơn phong (unimodal function) trong $\mathcal{O}(\log N)$.

2. Bản chất toán học của tính đơn điệu (Monotonicity Criterion)

2.1. Điều kiện tiên quyết để chặt nhị phân

Một bài toán có thể giải bằng chặt nhị phân kết quả khi và chỉ khi hàm kiểm tra check(X)tính đơn điệu trên toàn bộ không gian tìm kiếm:

$$\text{Không gian tìm Min:} \quad [\text{False, False, False, } \dots \mathbf{\text{True, True, True}}]$$ $$\text{Không gian tìm Max:} \quad [\text{True, True, True, } \dots \mathbf{\text{False, False, False}}]$$

Điểm chuyển giao giữa FalseTrue (hoặc TrueFalse) chính là nghiệm tối ưu toàn cục cần tìm.

2.2. Bảng mô phỏng: Bài toán chia $N$ đoạn gỗ thành $\ge K$ phần bằng nhau

Cho 3 khúc gỗ độ dài $[15, 20, 25]$, cần cắt thành ít nhất $K = 5$ đoạn có độ dài nguyên $X$. Hàm kiểm tra: $\text{check}(X) = \lfloor 15/X \rfloor + \lfloor 20/X \rfloor + \lfloor 25/X \rfloor \ge 5$.

Độ dài thử $X$ Số đoạn cắt được Điều kiện $\ge 5$ (check(X)) Đánh giá & Thu hẹp không gian
$1$ $15 + 20 + 25 = 60$ True Khả thi $\implies$ Thử tăng $X$
$5$ $3 + 4 + 5 = 12$ True Khả thi $\implies$ Thử tăng $X$
$10$ $1 + 2 + 2 = 5$ True Khả thi (Ghi nhận đáp án $X = 10$)
$11$ $1 + 1 + 2 = 4$ False Không đủ đoạn $\implies$ Giảm $X$
$12$ $1 + 1 + 2 = 4$ False Không đủ đoạn

$$\implies \text{Độ dài lớn nhất tìm được là } X = \mathbf{10}.$$


3. Hai mẫu cài đặt chặt nhị phân chuẩn thi đấu (Không bao giờ lặp vô tận)

3.1. Mẫu 1: Tìm giá trị nhỏ nhất thỏa mãn check(mid) == true (Tìm Min)

long long low = MIN_VAL, high = MAX_VAL;
long long ans = -1;

while (low <= high) {
    long long mid = low + (high - low) / 2;
    if (check(mid)) {
        ans = mid;        // Ghi nhận nghiệm hợp lệ
        high = mid - 1;   // Thu hẹp về nửa trái để tìm nghiệm nhỏ hơn
    } else {
        low = mid + 1;    // Không đạt, buộc phải tăng nghiệm
    }
}

3.2. Mẫu 2: Tìm giá trị lớn nhất thỏa mãn check(mid) == true (Tìm Max)

long long low = MIN_VAL, high = MAX_VAL;
long long ans = -1;

while (low <= high) {
    long long mid = low + (high - low) / 2;
    if (check(mid)) {
        ans = mid;        // Ghi nhận nghiệm hợp lệ
        low = mid + 1;    // Thu hẹp về nửa phải để tìm nghiệm lớn hơn
    } else {
        high = mid - 1;   // Quá lớn, phải giảm nghiệm
    }
}

Lưu ý chống tràn số: Luôn viết mid = low + (high - low) / 2 thay vì (low + high) / 2 để tránh tràn số khi low + high > 2 \cdot 10^9.


Chặt nhị phân tập số thực

4. Chặt nhị phân số thực

4.1. Tìm kiếm nhị phân trên số thực (Fixed Iterations)

Khi tìm nghiệm số thực, thay vì dùng while (high - low > EPS) dễ bị lỗi làm tròn vô tận, phương pháp chuẩn thi đấu là chạy lặp cố định 100 lần (đạt độ chính xác $\approx 2^{-100} \approx 10^{-30}$):

double low = 0.0, high = 1e9;
for (int iter = 0; iter < 100; ++iter) {
    double mid = (low + high) / 2.0;
    if (check_real(mid)) low = mid;
    else high = mid;
}
cout << fixed << setprecision(6) << low << "\n";

4.2. Tìm kiếm tam phân (Ternary Search) trên hàm cực đại

Chia đoạn $[low, high]$ thành 3 phần bằng 2 điểm $m_1 = low + \frac{high - low}{3}$ và $m_2 = high - \frac{high - low}{3}$:

  • Nếu $f(m_1) < f(m_2) \implies$ Cực đại nằm ở đoạn $[m_1, high] \implies low = m_1$.
  • Ngược lại $\implies high = m_2$.
double ternary_search_max(double low, double high) {
    for (int iter = 0; iter < 100; ++iter) {
        double m1 = low + (high - low) / 3.0;
        double m2 = high - (high - low) / 3.0;
        if (f(m1) < f(m2)) low = m1;
        else high = m2;
    }
    return f(low);
}

5. Mẫu cài đặt chuẩn thi đấu: Bài toán phân bổ công việc (Painter's Partition)

#include <bits/stdc++.h>
using namespace std;

// Kiểm tra xem có thể chia mảng thành <= K đoạn có tổng mỗi đoạn <= max_sum hay không
bool check(long long max_sum, const vector<long long> &a, int k) {
    int count = 1;
    long long current_sum = 0;
    for (long long x : a) {
        if (x > max_sum) return false;
        if (current_sum + x > max_sum) {
            count++;
            current_sum = x;
        } else {
            current_sum += x;
        }
    }
    return count <= k;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, k;
    if (!(cin >> n >> k)) return 0;

    vector<long long> a(n);
    long long low = 0, high = 0;
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
        low = max(low, a[i]);
        high += a[i];
    }

    long long ans = high;
    while (low <= high) {
        long long mid = low + (high - low) / 2;
        if (check(mid, a, k)) {
            ans = mid;
            high = mid - 1;
        } else {
            low = mid + 1;
        }
    }

    cout << ans << "\n";
    return 0;
}

6. Ranh giới áp dụng: Khi nào chặt nhị phân mảng vs Chặt nhị phân kết quả?

Đặc Điểm Binary Search trên Mảng Binary Search trên Đáp Án (Answer)
Đối tượng tìm kiếm Vị trí / phần tử trong mảng tĩnh Giá trị mục tiêu $X$ trong không gian nghiệm $[L, R]$
Yêu cầu bắt buộc Mảng đã được sắp xếp Hàm kiểm tra $\text{check}(X)$ có tính đơn điệu
Độ phức tạp $\mathcal{O}(\log N)$ $\mathcal{O}(\text{Time}(\text{check}) \times \log(\text{Range}))$
Dấu hiệu đề bài "Tìm vị trí đầu tiên $\ge K$" "Tìm giá trị lớn nhất / nhỏ nhất sao cho..."

1
A
B
C
D
2
A
B
C
D
3
A
B
C
D
4
A
B
C
D
5
A
B
C
D

Bài tập lập trình vận dụng

22 Bài tập thực hành

Nhấn vào nút "Làm bài" bên dưới để mở giao diện làm bài trực tuyến (Online Judge) và thực hiện viết mã nguồn cho bài tập này.

Chặt nhị phân cắt gỗ (eko)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Chia bánh pizza đều nhau
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Chuồng bò xa nhau nhất (aggressive cows)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Phân chia công việc thợ sơn (painter's partition)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Đoàn tàu vận chuyển hàng hóa
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Khoảng cách dây cáp nhỏ nhất
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Trung bình cộng đoạn con lớn nhất $\ge k$
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tối ưu hóa chi phí lắp trạm phát sóng
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tìm phần tử nhỏ thứ k trong bảng nhân $n \times n$
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tối ưu phân đoạn trọng số ma trận 2d
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tìm nghiệm thực của phương trình phi tuyến
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Đếm số cặp $(a_i, b_j)$ có tổng trong khoảng $[l, r]$
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Phần tử nhỏ thứ k của hợp hai mảng đã sắp xếp
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tối ưu phân đoạn trọng số ma trận 2d
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Chặt nhị phân song song (parallel binary search)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Khoảng cách cực trị trên đa giác lồi
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Chặt nhị phân song song
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tìm cực tiểu của hàm bậc hai
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Trung vị của hai mảng đã sắp xếp
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tam giác có diện tích lớn nhất
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Chat nhi phan khoang cach k diem
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Chat nhi phan phan so toi gian
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài