#include <bits/stdc++.h>
using namespace std;
namespace Obstacles {
static const int MAXV = 11; // vì T,H ∈ [0..10] theo đề
int N, M;
vector<int> Trow, Hcol;
// prefix min/max của T
vector<int> prefMinT, prefMaxT;
// lastGreater[h] = r lớn nhất sao cho prefMinT[r] > h (h=0..10), -1 nếu không có
int lastGreater[MAXV];
// Sparse Table cho RMQ min(H)
vector<int> lg2;
vector<vector<int>> st; // st[k][i] = min trên [i, i+2^k-1]
// Với mỗi ngưỡng t (0..10): rào trái/phải gần nhất có H >= t
vector<vector<int>> prevGE, nextGE; // [11][M]
inline int rmqMinH(int l, int r) {
// luôn gọi với l <= r; phòng hờ:
if (l > r) return INT_MAX;
int len = r - l + 1, k = lg2[len];
return min(st[k][l], st[k][r - (1 << k) + 1]);
}
// Dải cột quanh X trong [L,R] với điều kiện H < t
inline pair<int,int> component_bounds(int L, int R, int X, int t) {
// rào trái = prevGE[t][X] (chỉ số rào cuối cùng < X), rào phải = nextGE[t][X] (chỉ số rào đầu tiên > X)
int Lbar = prevGE[t][X];
int Rbar = nextGE[t][X];
int Lb = max(L, Lbar + 1);
int Rb = min(R, (Rbar == M ? R : Rbar - 1));
return {Lb, Rb};
}
} // namespace Obstacles
using namespace Obstacles;
// ---------- initialize ----------
void initialize(vector<int> T, vector<int> H) {
Trow = move(T);
Hcol = move(H);
N = (int)Trow.size();
M = (int)Hcol.size();
// prefix min/max của T
prefMinT.resize(N);
prefMaxT.resize(N);
for (int i = 0; i < N; ++i) {
if (i == 0) prefMinT[i] = prefMaxT[i] = Trow[i];
else {
prefMinT[i] = min(prefMinT[i-1], Trow[i]);
prefMaxT[i] = max(prefMaxT[i-1], Trow[i]);
}
}
// lastGreater[h] cho h=0..10 (O(N*11), rất nhỏ)
for (int h = 0; h < MAXV; ++h) lastGreater[h] = -1;
for (int r = 0; r < N; ++r) {
int upTo = min(prefMinT[r] - 1, MAXV - 1);
for (int h = 0; h <= upTo; ++h) lastGreater[h] = r;
}
// Sparse Table trên H (min)
lg2.assign(M + 1, 0);
for (int i = 2; i <= M; ++i) lg2[i] = lg2[i >> 1] + 1;
int K = lg2[M];
st.assign(K + 1, vector<int>(M));
for (int j = 0; j < M; ++j) st[0][j] = Hcol[j];
for (int k = 1; k <= K; ++k) {
int half = 1 << (k - 1);
for (int j = 0; j + (1 << k) <= M; ++j) {
st[k][j] = min(st[k-1][j], st[k-1][j + half]);
}
}
// prevGE/nextGE cho mọi t = 0..10
prevGE.assign(MAXV, vector<int>(M));
nextGE.assign(MAXV, vector<int>(M));
for (int t = 0; t < MAXV; ++t) {
int last = -1;
for (int j = 0; j < M; ++j) {
prevGE[t][j] = last;
if (Hcol[j] >= t) last = j;
}
int nxt = M;
for (int j = M - 1; j >= 0; --j) {
nextGE[t][j] = nxt;
if (Hcol[j] >= t) nxt = j;
}
}
}
// ---------- can_reach ----------
bool can_reach(int L, int R, int S, int D) {
// Theo đề, (0,S) và (0,D) luôn hợp lệ (T[0] > H[S], H[D]). :contentReference[oaicite:1]{index=1}
int tcur = Trow[0];
// Dải quanh S với t = T[0] (chắc chắn chứa S)
auto seg = component_bounds(L, R, S, tcur);
int Lb = seg.first, Rb = seg.second;
if (D >= Lb && D <= Rb) return true;
// Lặp mở rộng: mỗi vòng tăng tcur ⇒ dải quanh S rộng hơn; ≤ 11 vòng (miền 0..10)
for (int iter = 0; iter < MAXV + 5; ++iter) { // guard dư
// Lấy cột "dễ nhất" hiện tại: ẩm nhỏ nhất trong [Lb,Rb]
int hmin = rmqMinH(Lb, Rb); // 0..10 (và chắc chắn < tcur)
int rmax = lastGreater[hmin]; // sâu nhất có thể xuống (>=0 vì hmin < T[0])
if (rmax < 0) return false; // phòng hờ, về lý không xảy ra
// Chọn hàng có T lớn nhất trong [0..rmax] để nới dải ngang
int tnew = prefMaxT[rmax];
if (tnew <= tcur) return false; // không thể nới thêm ⇒ không tới được
tcur = tnew;
seg = component_bounds(L, R, S, tcur);
Lb = seg.first; Rb = seg.second;
if (D >= Lb && D <= Rb) return true;
}
return false; // guard
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |