Hướng giải của Nhảy Phải Số Lớn Hơn
Nhớ rằng hướng dẫn giải này chỉ nên sử dụng khi bế tắc, và tuyệt đối không nên sao chép mã nguồn kèm theo. Hãy tôn trọng tác giả bài tập và người viết hướng dẫn giải.
Nộp mã nguồn lời giải chính thức trước khi giải bài tập đó có thể khiến bạn bị ban.
Nộp mã nguồn lời giải chính thức trước khi giải bài tập đó có thể khiến bạn bị ban.
Tác giả:
Hướng dẫn giải: Nhảy Phải Số Lớn Hơn
Phân tích bài toán
Quy tắc chuyển trạng thái là: Từ vị trí \(i\), nhảy tới vị trí \(j > i\) nhỏ nhất thỏa mãn \(A[j] > A[i]\) (đây chính là bài toán tìm phần tử lớn hơn tiếp theo - Next Greater Element).
- Ta xác định
nxt[i]cho mọi \(i\) bằng cách sử dụng Monotonic Stack chạy ngược từ cuối mảng về đầu trong độ phức tạp \(O(N)\). Với vị trí không có phần tử lớn hơn phía sau, ta trỏ tới một nút ảo \(N\). - Sau khi có mảng chuyển trạng thái
nxt[i], bài toán quay về việc mô phỏng nhảy đúng \(K\) bước trên đồ thị hàm số. Ta tiền xử lý bảngup[i][j]bằng phương pháp Binary Lifting. - Thực hiện truy vấn trong \(O(\log K)\). Nếu điểm dừng là nút ảo \(N\), in ra
-1.
Độ phức tạp
- Thời gian: \(O(N \log K_{max})\) tiền xử lý, và \(O(\log K)\) mỗi truy vấn.
- Không gian: \(O(N \log K_{max})\) bộ nhớ.
Mã nguồn C++ mẫu
#include <bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n, q;
if (!(cin >> n >> q)) return 0;
vector<int> a(n);
for (int i = 0; i < n; i++) cin >> a[i];
vector<int> nxt(n + 1);
nxt[n] = n;
stack<int> st;
for (int i = n - 1; i >= 0; i--) {
while (!st.empty() && a[st.top()] <= a[i]) {
st.pop();
}
if (st.empty()) nxt[i] = n;
else nxt[i] = st.top();
st.push(i);
}
int LOG = 20;
vector<vector<int>> up(n + 1, vector<int>(LOG));
for (int i = 0; i <= n; i++) {
up[i][0] = nxt[i];
}
for (int j = 1; j < LOG; j++) {
for (int i = 0; i <= n; i++) {
up[i][j] = up[up[i][j - 1]][j - 1];
}
}
while (q--) {
int u, k;
cin >> u >> k;
u--;
for (int j = 0; j < LOG; j++) {
if (k & (1 << j)) {
u = up[u][j];
}
}
if (u == n) cout << -1 << "\n";
else cout << u + 1 << "\n";
}
return 0;
}
Nhận xét