Trong bài toán này, ta nhận thấy không còn cách nào khác ngoài việc xây dựng
tất cả K hoán vị theo yêu cầu và kiểm tra từng hoán vị. Xem cách sinh hoán
vị tiếp theo trong thứ tự từ điển ở đây.
Để full điểm, ngoài việc kiểm tra như trong đề bài mô tả, ta cần có thêm
một số cái nhìn tinh tế hơn.
Thứ nhất, do lượng hoán vị cần xét là \(K \leq 10^6 < 10!\), do vậy mọi hoán
vị cần xét dường như chỉ xoay quanh việc thay đổi thứ tự 10 phần tử cuối
cùng. Trên thực tế, sẽ có tối đa một lần có hơn 10 phần tử cuối cùng thay
đổi trong dãy hoán vị và việc này không làm ảnh hưởng nhiều tới tính hiệu
quả của nhận xét này.
Thứ hay, có thể phát biểu thuật toán T(p) với một chút khác biệt như :
- p có không nhiều hơn 1 phần tử, T(p) = true
- p có nhiều hơn 1 phần tử, gọi X là vị trí của phần tử lớn nhất trong p,
pL là các phần tử bên trái của X và pL là các phần tử bên phải của X, khi đó
T(p) = true khi:
- T(pL) = T(pR) = true
- Tất cả các phần tử trong pL nhỏ hơn tất cả các phần tử trong p
Cách phát biểu khác biệt này đưa ra một nhận xét tổng quát hơn: “T(p) = true
khi và chỉ khi không tồn tại 3 vị trí \(i < j < k\) mà \(p_k < p_i < p_j\)”.
Cách phát biểu mới này giúp ta có một thuật toán kiểm tra T(p) hiệu quả hơn
như sau: Để đảm bảo T(p) = true, với mọi vị trí j nằm trong p, gọi R là phần
tử nhỏ nhất phía bên phải j và L là phần tử lớn nhất nhỏ hơn \(p_j\) phía trái
j, ta phải đảm bảo rằng \(L < R\).
Tuy nhiên, trong thực tế ta chỉ cần kiểm tra điều kiện trên cho những phần
tử bị thay đổi so với hoán vị trước (khoảng 10 phần tử cuối cùng) nên thuật
toán có thể chạy trong thời gian cho phép.
Nguồn: Tạp chí tin học và nhà trường.