제출 #825464

#제출 시각아이디문제언어결과실행 시간메모리
825464Shreyan_PaliwalValley (BOI19_valley)C++17
0 / 100
206 ms29128 KiB
#pragma GCC optimize("Ofast") #include <bits/stdc++.h> using namespace std; template<typename T> string tostr(const T& value) { ostringstream oss; oss << value; return oss.str(); } template<typename... Args> string fstr(const string& format, Args... args) { string result = format; size_t pos = 0; size_t argIndex = 0; auto replaceArg = [&](const auto& arg) { pos = result.find("{}", pos); if (pos != string::npos) { result.replace(pos, 2, tostr(arg)); ++argIndex; } }; (replaceArg(args), ...); return result; } /* * Keeps mint objects modulo MOD constant */ // const int MOD = 1e9 + 7; // struct mint { // int x; // mint() { x = 0; } // mint(int X) { x = X; } // mint(long long X) { x = ((X % MOD) + MOD) % MOD; } // mint(unsigned long long X) { x = (X % MOD); } // mint pow(int k) { mint r = 1, a = *this; while (k) { if (k & 1) r *= a; a *= a; k >>= 1; } return r; } // mint& operator+=(mint o) { if ((x += o.x) >= MOD) x -= MOD; return *this; } // mint& operator-=(mint o) { if ((x += MOD - o.x) >= MOD) x -= MOD; return *this; } // mint& operator*=(mint o) { x = 1ll * x * o.x % MOD; return *this; } // mint& operator/=(mint o) { return (*this) *= o.pow(MOD - 2); } // mint operator+(mint o) const { return mint(*this) += o; } // mint operator-(mint o) const { return mint(*this) -= o; } // mint operator*(mint o) const { return mint(*this) *= o; } // mint operator/(mint o) const { return mint(*this) /= o; } // bool operator<(mint o) const { return x < o.x; } // friend ostream& operator<<(ostream& os, mint a) { os << a.x; return os; } // }; /* * Matrices * Multiplication */ // typedef vector<vector<int>> MAT; // struct Matrix { // MAT v; // Matrix(MAT V) { swap(v, V); } // Matrix(int a, int b) { v.resize(a, vector<int>(b, 0)); } // Matrix operator*(const Matrix& o) { // // assert(v[0].size() == o.v.size()); // Matrix M(v.size(), o.v[0].size()); // for (int i = 0; i < v.size(); i++) // for (int j = 0; j < o.v[0].size(); j++) // for (int k = 0; k < (int)v[0].size(); k++) // M.v[i][j] += v[i][k] * o.v[k][j]; // return M; // } // Matrix operator^(int k) { // if (k&1) return (((*this)*(*this))^(k/2))*(*this); // else return ((*this)*(*this))^(k/2); // } // }; /* * Segment Tree * - RANGE QUERY * - RANGE UPDATE */ // template<class T> // T identity; // [SET IDENTITY OF CLASS T, hardcode T classname] // struct ND { // ND* ch[2] = { nullptr, nullptr }; // T v, f; // inline void create() { // if (!ch[0]) ch[0] = new ND; // [POTENTIALLY UPDATE VALUES] // if (!ch[1]) ch[1] = new ND; // [POTENTIALLY UPDATE VALUES] // } // inline T merge(int l, int r) { // // [INSERT CODE FOR MERGE SEGMENT] // } // inline void push(int l, int r) { // create(); // // [INSERT CODE FOR PUSHING SEGMENT FLAG] // } // void upd(int l, int r, int L, int R, T K) { // push(l, r); // if (R < l || r < L) return; // if (L <= l && r <= R) { // // [INSERT CODE FOR UPDATE SEGMENT] // return; // } // int m = (l + r) >> 1; // ch[0]->upd(l, m, L, R, K); // ch[1]->upd(m+1, r, L, R, K); // merge(l, r); // } // T qry(int l, int r, int L, int R) { // push(l, r); // if (R < l || r < L) return identity; // if (L <= l && r <= R) return v; // int m = (l + r) >> 1; // return OPERATION(ch[0]->qry(l,m,L,R), ch[1]->qry(m+1,r,L,R)); // } // ~ND() { delete ch[0]; delete ch[1]; ch[0] = ch[1] = nullptr; } // }; /* * Convex Hull Trick * - ORDERED SLOPES * - UNORDERED QUERIES O(N log N), ORDERED QUERIES O(N) */ // struct F { // int a, b; // F() {} // F(int A, int B) : a(A), b(B){ if (b<0) a*=-1, b*=-1; } // bool operator<(F o) const { return a*o.b < b*o.a; } // bool operator<=(F o) const { return a*o.b <= b*o.a; } // }; // struct L { // int m, b; // int operator()(int x) { return m*x + b; } // F operator^(L o) { return F{b-o.b,o.m-m}; } // }; // struct CHT { // vector<L> h; // // deque<L> h; // if using SECOND CODE in QRY FUNCTION // void add(L l) { // // // min hull + decreasing slopes OR max hull + increasing slopes // // while (h.size() >= 2 && (h.end()[-2]^l) <= (h.end()[-2]^h.back())) h.pop_back(); // // h.push_back(l); // // // min hull + increasing slopes OR max hull + decreasing slopes // // while (h.size() >= 2 && (h.end()[-2]^h.back()) <= (h.end()[-2]^l)) h.pop_back(); // // h.push_back(l); // } // int qry(int x) { // // O(N log N) time, unordered queries // // int lo = 0, hi = h.size()-1; // // while (lo < hi) { // // int m = (lo + hi) >> 1; // // if (h[m](x) < h[m+1](x)) // < or > depending on min/max qry // // lo = m+1; // // else // // hi = m; // // } // // return h[lo](x); // // if need O(N) time, use **DEQUE INSTEAD OF VECTOR** & use code below // // while (h.size() >= 2 && h[1](x) < h[0](x)) h.pop_front(); // < or > depending on min/max qry // // return h[0](x); // } // }; /* * Li Chao Tree * UNORDERED SLOPES, UNORDERED QUERIES O(N log N) * Extension of segment tree */ // struct F { // int a, b; // F() {} // F(int A, int B) : a(A), b(B){ if (b<0) a*=-1, b*=-1; } // bool operator<(F o) const { return a*o.b < b*o.a; } // bool operator<=(F o) const { return a*o.b <= b*o.a; } // }; // struct L { // int m, b; // int operator()(int x) { return m*x + b; } // F operator^(L o) { return F{b-o.b,o.m-m}; } // }; // // #define OP(a, b) (a < b) // DEFINE OPERATOR // // #define OPR(a, b) (min(a,b)) // DEFINE OPERATOR // #define OP(a, b) (a > b) // #define OPR(a, b) (max(a,b)) // struct ND { // ND * ch[2] = { nullptr, nullptr }; // L v = L{1, 0}; // void create() { // if (!ch[0]) { ch[0] = new ND; ch[0]->v = v; } // if (!ch[1]) { ch[1] = new ND; ch[1]->v = v; } // } // void upd(int l, int r, L V) { // // update the li chao tree with line V // if (v.m == V.m && v.b == V.b) return; // if (l == r) { // // if new line is better, swap // if (OP(V(l), v(l))) swap(V, v); // return; // } // create(); // int m = (l + r) >> 1; // midpoint // if (OP(V(m), v(m))) swap(V, v); // if new line is better at mid, it has one half, so swap // F x = v ^ V; // intersection of two lines // if (x <= F(m, 1)) // ch[0]->upd(l, m, V); // else // ch[1]->upd(m+1, r, V); // } // int qry(int l, int r, int X) { // // qry li chao tree for x coord X // int ret = v(X); // gets value for current segment // if (l != r) { // int m = (l + r) >> 1; // if (X <= m && ch[0] != nullptr) return OPR(ret, ch[0]->qry(l, m, X)); // if (X > m && ch[1] != nullptr) return OPR(ret, ch[1]->qry(m+1, r, X)); // } // return ret; // } // }; // #undef OP // #undef OPR const int maxn = 100000; const int INF = 2000000000; int n, s, q, e; // nodes, numshops, numqueries, valleynode vector<pair<int,int>> adj[maxn]; pair<int,int> edges[maxn]; int shop[maxn]; // is shop? int closest[maxn]; // closest shop in subtree int dist[maxn]; // distance to root, set int dpth[maxn]; // depth from root, set int bl[maxn][20]; // set int bld[maxn][20]; // array[nd] = - 2 * dist[nd] + min(dist[shop]) for shop in subtree[dist] void dfs(int nd, int par, int pardist, int d) { // set depth dpth[nd] = d; // set binary lifting bl[nd][0] = par; for (int i = 1; i < 20; i++) bl[nd][i] = bl[bl[nd][i-1]][i-1]; // recurse dfs, set distance from root for (auto i : adj[nd]) if (i.first != par) { dist[i.first] = dist[nd] + i.second; dfs(i.first, nd, i.second, d+1); } // init closest shop in subtree closest[nd] = shop[nd] ? 0 : INF; for (auto i : adj[nd]) if (i.first != par) closest[nd] = min(closest[nd], i.second + closest[i.first]); return; } void dfs_bld(int nd) { if (closest[nd] == INF) bld[nd][0] = INF; else bld[nd][0] = -dist[nd] + closest[nd]; for (int i = 1; i < 20; i++) bld[nd][i] = min(bld[nd][i-1], bld[bl[nd][i-1]][i-1]); for (auto i : adj[nd]) if (i.first != bl[nd][0]) dfs_bld(i.first); } inline int jmp(int nd, int k) { for (int i = 19; i >= 0; i--) if ((k >> i) & 1) nd = bl[nd][i]; return nd; } inline bool on_path(int nd, int nd2) { // checking if nd2 is on nd's path to root return (dpth[nd] >= dpth[nd2] && jmp(nd, dpth[nd] - dpth[nd2]) == nd2); } void solve() { cin >> n >> s >> q >> e; e--; for (int i = 0; i < n-1; i++) { int c; cin >> edges[i].first >> edges[i].second >> c; edges[i].first--, edges[i].second--; adj[edges[i].first].push_back({edges[i].second, c}); adj[edges[i].second].push_back({edges[i].first, c}); } for (int i = 0; i < s; i++) { int a; cin >> a; a--; shop[a] = 1; } dfs(e, e, 0, 0); dfs_bld(e); for (int i = 0; i < q; i++) { // a is edge removed, b is node to find int a, b; cin >> a >> b; a--, b--; // check if escape possible if (!on_path(b, edges[a].first) || !on_path(b, edges[a].second)) { cout << "escaped" << endl; continue; } // not possible, so search if (dpth[edges[a].first] < dpth[edges[a].second]) swap(edges[a].first, edges[a].second); int val = INF; int B = b; for (int i = 19; i >= 0; i--) if (((dpth[edges[a].first] - dpth[b]) >> i) & 1) val = min(val, bld[b][i]), b = bl[b][i]; if (val == INF) { cout << "oo" << endl; continue; } cout << val + dist[B] << endl; continue; } } signed main() { cin.tie(nullptr) -> ios::sync_with_stdio(false); // freopen("main.in", "r", stdin); int t; // cin >> t; t=1; while(t--) solve(); return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...