Submission #1265029

#TimeUsernameProblemLanguageResultExecution timeMemory
1265029Kanon장애물 (IOI25_obstacles)C++20
10 / 100
274 ms108724 KiB
#include <bits/stdc++.h> using namespace std; template <typename A, typename B> string to_string(pair<A, B> p); template <typename A, typename B, typename C> string to_string(tuple<A, B, C> p); template <typename A, typename B, typename C, typename D> string to_string(tuple<A, B, C, D> p); string to_string(const string& s) { return '"' + s + '"'; } string to_string(const char* s) { return to_string((string) s); } string to_string(bool b) { return (b ? "true" : "false"); } string to_string(vector<bool> v) { bool first = true; string res = "{"; for (int i = 0; i < static_cast<int>(v.size()); i++) { if (!first) { res += ", "; } first = false; res += to_string(v[i]); } res += "}"; return res; } template <size_t N> string to_string(bitset<N> v) { string res = ""; for (size_t i = 0; i < N; i++) { res += static_cast<char>('0' + v[i]); } return res; } template <typename A> string to_string(A v) { bool first = true; string res = "{"; for (const auto &x : v) { if (!first) { res += ", "; } first = false; res += to_string(x); } res += "}"; return res; } template <typename A, typename B> string to_string(pair<A, B> p) { return "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; } template <typename A, typename B, typename C> string to_string(tuple<A, B, C> p) { return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")"; } template <typename A, typename B, typename C, typename D> string to_string(tuple<A, B, C, D> p) { return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")"; } void debug_out() { cerr << endl; } template <typename Head, typename... Tail> void debug_out(Head H, Tail... T) { cerr << " " << to_string(H); debug_out(T...); } #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__); template <typename T, class F = function<T(const T&, const T&)>> class SparseTable { public: int n; vector<vector<T>> mat; F func; SparseTable(const vector<T>& a, const F& f) : func(f) { n = static_cast<int>(a.size()); int max_log = 32 - __builtin_clz(n); mat.resize(max_log); mat[0] = a; for (int j = 1; j < max_log; j++) { mat[j].resize(n - (1 << j) + 1); for (int i = 0; i <= n - (1 << j); i++) { mat[j][i] = func(mat[j - 1][i], mat[j - 1][i + (1 << (j - 1))]); } } } T get(int from, int to) const { assert(0 <= from && from <= to && to <= n - 1); int lg = 32 - __builtin_clz(to - from + 1) - 1; return func(mat[lg][from], mat[lg][to - (1 << lg) + 1]); } }; struct edge { int to; int val; edge(){ to = INT_MAX; val = INT_MIN; }; edge(int _to, int _val) : to(_to), val(_val) {}; }; void debug_out(edge e) { debug_out(make_pair(e.to, e.val)); } void debug_out(vector<edge> e) { vector<pair<int, int>> ee; for (auto i : e) ee.push_back({i.to, i.val}); debug_out(ee); } int Lg = 18; vector<vector<edge>> toL; vector<vector<edge>> toR; void initialize(std::vector<int> T, std::vector<int> H) { T.push_back(0); int n = H.size(); int N = T.size(); vector<int> a(n); { vector<int> order(n); iota(order.begin(), order.end(), 0); sort(order.begin(), order.end(), [&](int i, int j){return H[i] < H[j];}); int pre = 0; for (int i : order) { a[i] = pre; while (a[i] < N && H[i] >= T[a[i]]) a[i]++; pre = a[i]; } } SparseTable tab_T(T, [&](int i, int j){return min(i, j);}); SparseTable tab_H(H, [&](int i, int j){return min(i, j);}); auto height = [&](int i) { if (i >= 0 && i < n) return a[i]; return N; }; auto First_block = [&](int L, int R, int val, int side) { bool valid = tab_H.get(L, R) < val; if (!valid) return side == 1 ? -1 : n; while (R > L) { int mid = (L + R) / 2; bool LL = tab_H.get(L, mid) < val; bool RR = tab_H.get(mid + 1, R) < val; assert(LL || RR); if (!LL) L = mid + 1; else if (!RR) R = mid; else { if (side == 1) L = mid + 1; else R = mid; } } return R; }; vector<edge> Lpar(n); vector<edge> Rpar(n); vector<int> que = {-1}; for (int i = 0; i < n; i++) { while (que.size() && height(que.back()) <= height(i)) que.pop_back(); if (que.size()) Lpar[i] = edge(que.back(), 0); que.push_back(i); } que = (vector<int>) {n}; for (int i = n - 1; i >= 0; i--) { while (que.size() && height(que.back()) <= height(i)) que.pop_back(); if (que.size()) Rpar[i] = edge(que.back(), 0); que.push_back(i); } { vector<int> order(n); iota(order.begin(), order.end(), 0); sort(order.begin(), order.end(), [&](int i, int j){return a[i] > a[j];}); for (int i : order) { int Lp = Lpar[i].to; if (Lp == INT_MAX) continue; int Rp = Rpar[i].to; assert(Rp != INT_MAX); int val = height(Rp) >= height(Lp) ? -1 : Lpar[Rp].val; int min_T = tab_T.get(height(i), min(height(Lp), height(Rp)) - 1); int nxt = First_block(Lp + 1, Rp - 1, min_T, -1); Lpar[i].val = max(nxt, val); } for (int i : order) { int Rp = Rpar[i].to; if (Rp == INT_MAX) continue; int Lp = Lpar[i].to; assert(Lp != INT_MAX); int val = height(Lp) >= height(Rp) ? n : Rpar[Lp].val; int min_T = tab_T.get(height(i), min(height(Lp), height(Rp)) - 1); int nxt = First_block(Lp + 1, Rp - 1, min_T, +1); Rpar[i].val = min(nxt, val); } } toL = vector<vector<edge>>(n, vector<edge>(Lg)); toR = vector<vector<edge>>(n, vector<edge>(Lg)); for (int i = 0; i < n; i++) { toL[i][0] = Lpar[i]; toR[i][0] = Rpar[i]; } for (int d = 1; d < Lg; d++) { for (int i = 0; i < n; i++) { int pL = toL[i][d - 1].to; int pR = toR[i][d - 1].to; if (0 <= pL && pL <= n - 1) { toL[i][d].to = toL[pL][d - 1].to; toL[i][d].val = max(toL[pL][d - 1].val, toL[i][d - 1].val); } if (0 <= pR && pR <= n - 1) { toR[i][d].to = toR[pR][d - 1].to; toR[i][d].val = min(toR[pR][d - 1].val, toR[i][d - 1].val); } } } } bool can_reach(int L, int R, int S, int D) { if (S > D) swap(S, D); if (S == D) return true; edge curS(S, 200000); for (int d = 0; d < Lg; d++) { int np = toR[curS.to][d].to; if (np == INT_MAX || np >= D) continue; curS.val = min(curS.val, toR[curS.to][d].val); curS.to = np; } if (curS.val < L) return false; edge curD(D, -1); for (int d = 0; d < Lg; d++) { int np = toL[curD.to][d].to; if (np == INT_MAX || np <= S) continue; curD.val = max(curD.val, toL[curD.to][d].val); curD.to = np; } if (curD.val > R) return false; return true; }
#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...