Khoá học C++ nâng cao
Bài học: Thư Viện STL C++ Nâng Cao
🏆 +100 XP tiềm năng Thoát

Thư Viện STL C++ Nâng Cao

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

Thư Viện STL C++ Nâng Cao

Nội dung bài học

1. Khái niệm & bản chất của các cấu trúc dữ liệu STL nâng cao

Thư viện mẫu chuẩn C++ (Standard Template Library - STL) cung cấp các cấu trúc dữ liệu trừu tượng hiệu năng cao được xây dựng trên nền tảng Cây đỏ-đen (Red-Black Tree)Bảng băm (Hash Table):

  • set / multiset / map: Cấu trúc cây tự cân bằng (Balanced BST), duy trì các phần tử luôn được sắp xếp có thứ tự, hỗ trợ thêm, xóa, tìm kiếm, tìm kiếm nhị phân (lower_bound, upper_bound) trong thời gian logarit $\mathcal{O}(\log N)$.
  • unordered_set / unordered_map: Cấu trúc bảng băm (Hash Table), đạt độ phức tạp trung bình $\mathcal{O}(1)$ cho các thao tác tìm kiếm và thêm xóa (nhưng có thể suy biến về $\mathcal{O}(N)$ khi bị đụng độ băm).
  • priority_queue (Hàng đợi ưu tiên): Cấu trúc đống nhị phân (Binary Heap), luôn duy trì phần tử lớn nhất (Max-Heap) hoặc nhỏ nhất (Min-Heap) ở đỉnh trong $\mathcal{O}(1)$, thêm và xóa trong $\mathcal{O}(\log N)$.
  • Tùy biến hàm so sánh (Custom Struct Comparator / Functor): Tùy chỉnh trật tự sắp xếp phức tạp cho các cấu trúc dữ liệu STL.

2. Bảng so sánh cấu trúc & hiệu năng của các Container STL

Container STL Cấu Trúc Ngầm Định Trật Tự Dữ Liệu Thao Tác Thêm / Xóa / Tìm Tìm Kiếm Nhị Phân (lower_bound)
vector<T> Mảng động liên tiếp Theo thứ tự chèn $\mathcal{O}(1)$ cuối, $\mathcal{O}(N)$ giữa Cần sort trước $\mathcal{O}(\log N)$
set<T> Cây đỏ-đen (Red-Black Tree) Tăng dần, duy nhất $\mathcal{O}(\log N)$ s.lower_bound(x) trong $\mathcal{O}(\log N)$
multiset<T> Cây đỏ-đen Tăng dần, cho phép trùng $\mathcal{O}(\log N)$ ms.lower_bound(x) trong $\mathcal{O}(\log N)$
unordered_set<T> Bảng băm (Hash Table) Không có thứ tự Trung bình $\mathcal{O}(1)$, xấu nhất $\mathcal{O}(N)$ Không hỗ trợ
priority_queue<T> Đống nhị phân (Max-Heap) Phần tử cực trị ở đỉnh push/pop $\mathcal{O}(\log N)$, top $\mathcal{O}(1)$ Không hỗ trợ

3. Tử huyệt lập trình: Bẫy xóa phần tử trong multiset & Bẫy unordered_map

Cảnh báo bẫy lỗi 1: BẪY XÓA TẤT CẢ PHẦN TỬ TRÙNG NHAU TRONG MULTISET

Trong multiset<int> ms, nếu viết ms.erase(val), C++ sẽ xóa sạch toàn bộ mọi phần tử có giá trị bằng val!
Cách xóa đúng duy nhất 1 phần tử: Truyền vào iterator trỏ tới phần tử đó: cpp auto it = ms.find(val); if (it != ms.end()) { ms.erase(it); // Chỉ xóa đúng 1 phần tử tại vị trí it }

Cảnh báo bẫy lỗi 2: BẪY TẤN CÔNG BẢNG BĂM (ANTI-HASH TEST / HASH COLLISION)

unordered_map mặc định trong libstdc++ dùng hàm băm chia dư đơn giản, dễ bị các bộ test sinh đối kháng (Anti-hash tests) làm đụng độ băm khiến thời gian chạy tụt từ $\mathcal{O}(1)$ xuống $\mathcal{O}(N) \implies \text{TLE}$.
Giải pháp: Sử dụng Custom Hash kết hợp thời gian hệ thống (Chrono): cpp struct custom_hash { static uint64_t splitmix64(uint64_t x) { x += 0x9e3779b97f4a7c15; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return x ^ (x >> 31); } size_t operator()(uint64_t x) const { static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count(); return splitmix64(x + FIXED_RANDOM); } }; unordered_map<long long, int, custom_hash> safe_map;


Hai Heap duy trì Trung vị động

4. Mẫu cài đặt chuẩn thi đấu: Duy trì trung vị

Bài toán: Cho một luồng số liên tục, sau mỗi số được thêm vào, hãy in ra trung vị của toàn bộ các số đã nhập.

  • Chiến lược 2 Heap:
  • Max-Heap left_heap chứa nửa nhỏ hơn của dãy số.
  • Min-Heap right_heap chứa nửa lớn hơn của dãy số.
  • Duy trì kích thước: left_heap.size() luôn bằng right_heap.size() hoặc hơn đúng $1$ phần tử.
  • Trung vị luôn là left_heap.top().
#include <bits/stdc++.h>
using namespace std;

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

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

    priority_queue<int> left_heap; // Max-heap
    priority_queue<int, vector<int>, greater<int>> right_heap; // Min-heap

    for (int i = 0; i < n; ++i) {
        int x;
        cin >> x;

        if (left_heap.empty() || x <= left_heap.top()) left_heap.push(x);
        else right_heap.push(x);

        // Cân bằng kích thước
        if (left_heap.size() > right_heap.size() + 1) {
            right_heap.push(left_heap.top());
            left_heap.pop();
        } else if (right_heap.size() > left_heap.size()) {
            left_heap.push(right_heap.top());
            right_heap.pop();
        }

        cout << left_heap.top() << " ";
    }
    cout << "\n";
    return 0;
}

5. Ranh giới áp dụng

Mục Đích Chọn Container Phù Hợp
Cần tập hợp phần tử duy nhất, liên tục tìm $\ge X$ set<T>
Cần tập hợp có phần tử trùng lặp, liên tục lấy $\min/\max$ và xóa multiset<T>
Chỉ cần đếm tần suất cực nhanh không cần thứ tự unordered_map<T, int, custom_hash>
Liên tục tìm phần tử lớn nhất/nhỏ nhất, không cần tìm kiếm tùy ý priority_queue<T>

1
A
B
C
D
2
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.

Duy trì trung vị động
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Đếm tần suất giá trị bằng safe hash map
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Nối dây tiết kiệm bằng priority queue
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Duy trì trung vị động (running median)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tìm phần tử kế tiếp nhỏ nhất lớn hơn x
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Lập lịch phòng họp đa năng (meeting rooms)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Duy trì k phần tử lớn nhất trong luồng dữ liệu
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tối ưu hóa chi phí mua cổ phiếu theo thời gian
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Hệ thống đặt chỗ rạp chiếu phim tối ưu
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Đếm số phần tử phân biệt trong mọi cửa sổ k
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Hợp nhất các đoạn số rời rạc (merge intervals)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tìm cặp điểm có khoảng cách manhattan nhỏ nhất
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Hệ thống xếp hạng trực tuyến đa tiêu chí
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tối ưu phân bổ băng thông máy chủ (server load balancer)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Duy trì tổng của k phần tử lớn nhất động
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Kỹ thuật small-to-large merging trên STL map
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Ordered set PBDS truy van thu hang
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Can bang hai heap running median
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Multiset interval management
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Safe unordered map custom hash
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Priority queue Dijkstra custom comparator
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
LRU cache implementation STL
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài