Submission #1322740

#TimeUsernameProblemLanguageResultExecution timeMemory
1322740lucas110550Obstacles for a Llama (IOI25_obstacles)C++20
83 / 100
118 ms28260 KiB
// Your solution code here #include <bits/stdc++.h> using namespace std; /* IOI 2025 "Obstacles for a Llama" – specialized variant where L=0, R=M-1 always. We preprocess the unique connected component (in the whole grid of free cells) that each top-row column belongs to, then each query is O(1). Key ingredients (adapted from known solution ideas for this task): - nearest strictly smaller humidity on left/right (lf, rg) - range maximum query on H to test whether a whole horizontal interval can be crossed - bestTemp(h): maximum temperature reachable by going down using a column of humidity h (i.e., among rows r such that min_{0..r} T > h) */ static int N_, M_; static vector<int> T_, H_; static vector<int> prefMinT_; // prefMinT_[i] = min(T[0..i]) (non-increasing) static vector<int> prefMaxT_; // prefMaxT_[i] = max(T[0..i]) (non-decreasing) static vector<int> lg2_; static vector<vector<int>> stMaxH_; // sparse table for max on H static vector<int> lf_, rg_; // nearest strictly smaller humidity indices static vector<int> minVal_; // minVal_[j] = minimal humidity value reachable from column j (top row) static vector<int> compL_, compR_; // final component interval [L,R] under threshold bestTemp(minVal) static inline int rangeMaxH(int l, int r) { if (l > r) std::swap(l, r); int len = r - l + 1; int k = lg2_[len]; return max(stMaxH_[k][l], stMaxH_[k][r - (1 << k) + 1]); } // bestTemp(h): max temperature T[x] among rows x where prefMinT_[x] > h. // If no such row exists, return -1. static inline int bestTemp(int h) { int lo = 0, hi = N_ - 1, ans = -1; while (lo <= hi) { int mid = (lo + hi) >> 1; if (prefMinT_[mid] > h) { ans = mid; lo = mid + 1; } else { hi = mid - 1; } } return (ans == -1 ? -1 : prefMaxT_[ans]); } static inline int leftBoundary(int pos, int t) { // smallest L in [0..pos] such that max(H[L..pos]) < t int lo = 0, hi = pos, ans = pos; while (lo <= hi) { int mid = (lo + hi) >> 1; if (rangeMaxH(mid, pos) < t) { ans = mid; hi = mid - 1; } else { lo = mid + 1; } } return ans; } static inline int rightBoundary(int pos, int t) { // largest R in [pos..M-1] such that max(H[pos..R]) < t int lo = pos, hi = M_ - 1, ans = pos; while (lo <= hi) { int mid = (lo + hi) >> 1; if (rangeMaxH(pos, mid) < t) { ans = mid; lo = mid + 1; } else { hi = mid - 1; } } return ans; } void initialize(std::vector<int> T, std::vector<int> H) { T_ = std::move(T); H_ = std::move(H); N_ = (int)T_.size(); M_ = (int)H_.size(); // prefix min/max on T prefMinT_.assign(N_, 0); prefMaxT_.assign(N_, 0); { int mn = INT_MAX, mx = INT_MIN; for (int i = 0; i < N_; i++) { mn = min(mn, T_[i]); mx = max(mx, T_[i]); prefMinT_[i] = mn; prefMaxT_[i] = mx; } } // sparse table for max on H lg2_.assign(M_ + 1, 0); for (int i = 2; i <= M_; i++) lg2_[i] = lg2_[i >> 1] + 1; int K = lg2_[M_] + 1; stMaxH_.assign(K, vector<int>(M_, 0)); stMaxH_[0] = H_; for (int k = 1; k < K; k++) { int half = 1 << (k - 1); int span = 1 << k; for (int i = 0; i + span <= M_; i++) { stMaxH_[k][i] = max(stMaxH_[k - 1][i], stMaxH_[k - 1][i + half]); } } // nearest strictly smaller on left (lf_) lf_.assign(M_, -1); { vector<int> st; st.reserve(M_); for (int i = 0; i < M_; i++) { while (!st.empty() && H_[st.back()] >= H_[i]) st.pop_back(); lf_[i] = st.empty() ? -1 : st.back(); st.push_back(i); } } // nearest strictly smaller on right (rg_) rg_.assign(M_, -1); { vector<int> st; st.reserve(M_); for (int i = M_ - 1; i >= 0; i--) { while (!st.empty() && H_[st.back()] >= H_[i]) st.pop_back(); rg_[i] = st.empty() ? -1 : st.back(); st.push_back(i); } } // Compute minVal_ in increasing order of humidity: // minVal[u] = min(H[u], minVal[v]) for v in {lf[u],rg[u]} that are "jumpable" from u. // Jump condition from u to v: // bestTemp(H[u]) > max(H[min(u,v)..max(u,v)]). minVal_.assign(M_, 0); vector<int> ord(M_); iota(ord.begin(), ord.end(), 0); stable_sort(ord.begin(), ord.end(), [&](int a, int b) { if (H_[a] != H_[b]) return H_[a] < H_[b]; return a < b; }); for (int u : ord) { int t = bestTemp(H_[u]); int best = H_[u]; if (t != -1) { int v = lf_[u]; if (v != -1 && t > rangeMaxH(u, v)) best = min(best, minVal_[v]); v = rg_[u]; if (v != -1 && t > rangeMaxH(u, v)) best = min(best, minVal_[v]); } minVal_[u] = best; } // Final component id for each column u: // t2 = bestTemp(minVal[u]), then component is the maximal interval containing u // where all humidities < t2 (i.e. max on interval < t2). compL_.assign(M_, 0); compR_.assign(M_, 0); for (int u = 0; u < M_; u++) { int t2 = bestTemp(minVal_[u]); if (t2 == -1) { compL_[u] = compR_[u] = u; } else { compL_[u] = leftBoundary(u, t2); compR_[u] = rightBoundary(u, t2); } } } bool can_reach(int /*L*/, int /*R*/, int S, int D) { // L=0, R=M-1 always in this version. return (compL_[S] == compL_[D] && compR_[S] == compR_[D]); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...