Hướng dẫn thuật toán

Trùm CUỐI 2026-01-11 11:03:49

Link bài tập

1. Phân tích bài toán

  • Yêu cầu: Tìm độ dài lớn nhất của một dãy con mà các phần tử đứng sau luôn lớn hơn phần tử đứng trước.
  • Đặc điểm: Với N = 1000 , chúng ta có thể sử dụng thuật toán có độ phức tạp O(N^2) .

2. Ý tưởng Quy hoạch động

  • Gọi dp[i] là độ dài của dãy con tăng dài nhất kết thúc tại phần tử a[i] .
  • Để tính dp[i], ta nhìn lại các phần tử a[j] đứng trước nó ( j < i ):
    • Nếu a[j] < a[i] , ta có thể kéo dài dãy con kết thúc tại j bằng cách thêm a[i] vào sau. Khi đó độ dài mới sẽ là dp[j] + 1.
    • Ta chọn giá trị lớn nhất có thể đạt được.

3. Các bước thuật toán

  1. Khởi tạo: Tạo một mảng dp N phần tử, tất cả giá trị ban đầu bằng 1 (vì mỗi phần tử đứng một mình luôn là một dãy con tăng độ dài 1).
  2. Duyệt và cập nhật:
    • Chạy vòng lặp i từ 1 đến N-1 .
    • Với mỗi i, chạy vòng lặp j từ 0 đến i-1 .
    • Nếu a[j] < a[i] :
      • Cập nhật: dp[i] = max(dp[i], dp[j] + 1).
  3. Kết quả: Đáp án của bài toán là giá trị lớn nhất trong mảng dp.

4. Lưu ý khi triển khai

  • C++: Có thể dùng hàm *max_element(dp, dp + n) để tìm kết quả cuối cùng.
  • Python: Dùng max(dp) để lấy độ dài lớn nhất.
  • Điều kiện "tăng nghiêm ngặt": Phải là a[j] < a[i] . Nếu đề bài cho phép các phần tử bằng nhau (dãy không giảm), bạn sẽ đổi thành a[j] \le a[i] .
  • Giới hạn: Với N lớn hơn (ví dụ 10^5 ), thuật toán O(N^2) này sẽ bị quá thời gian (TLE), khi đó cần dùng kỹ thuật kết hợp Tìm kiếm nhị phân để đạt độ phức tạp O(N \log N) . Tuy nhiên với N=1000 , cách O(N^2) là đơn giản và hiệu quả nhất.