結果
問題 | No.2337 Equidistant |
ユーザー | ebi_fly |
提出日時 | 2023-06-02 23:22:59 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 966 ms / 4,000 ms |
コード長 | 10,626 bytes |
コンパイル時間 | 2,257 ms |
コンパイル使用メモリ | 169,192 KB |
実行使用メモリ | 139,872 KB |
最終ジャッジ日時 | 2024-06-09 01:30:14 |
合計ジャッジ時間 | 15,125 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,816 KB |
testcase_01 | AC | 2 ms
6,940 KB |
testcase_02 | AC | 2 ms
6,940 KB |
testcase_03 | AC | 2 ms
6,940 KB |
testcase_04 | AC | 2 ms
6,944 KB |
testcase_05 | AC | 2 ms
6,944 KB |
testcase_06 | AC | 4 ms
6,940 KB |
testcase_07 | AC | 4 ms
6,940 KB |
testcase_08 | AC | 4 ms
6,940 KB |
testcase_09 | AC | 4 ms
6,944 KB |
testcase_10 | AC | 4 ms
6,944 KB |
testcase_11 | AC | 534 ms
111,544 KB |
testcase_12 | AC | 576 ms
111,548 KB |
testcase_13 | AC | 532 ms
111,528 KB |
testcase_14 | AC | 548 ms
111,468 KB |
testcase_15 | AC | 524 ms
111,532 KB |
testcase_16 | AC | 554 ms
112,004 KB |
testcase_17 | AC | 562 ms
112,000 KB |
testcase_18 | AC | 528 ms
111,532 KB |
testcase_19 | AC | 554 ms
111,640 KB |
testcase_20 | AC | 508 ms
111,552 KB |
testcase_21 | AC | 488 ms
139,872 KB |
testcase_22 | AC | 966 ms
111,964 KB |
testcase_23 | AC | 490 ms
112,196 KB |
testcase_24 | AC | 700 ms
130,528 KB |
testcase_25 | AC | 464 ms
112,404 KB |
testcase_26 | AC | 773 ms
129,992 KB |
testcase_27 | AC | 551 ms
112,064 KB |
testcase_28 | AC | 542 ms
112,156 KB |
ソースコード
#line 1 "a.cpp" #include <algorithm> #include <bitset> #include <cassert> #include <chrono> #include <climits> #include <cmath> #include <complex> #include <cstddef> #include <cstdint> #include <cstdlib> #include <cstring> #include <functional> #include <iomanip> #include <iostream> #include <limits> #include <map> #include <memory> #include <numeric> #include <optional> #include <queue> #include <random> #include <set> #include <stack> #include <string> #include <tuple> #include <type_traits> #include <unordered_map> #include <unordered_set> #include <utility> #include <vector> /* macro */ #define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++) #define rrep(i, a, n) for (int i = ((int)(n)-1); i >= (int)(a); i--) #define Rep(i, a, n) for (i64 i = (i64)(a); i < (i64)(n); i++) #define RRep(i, a, n) for (i64 i = ((i64)(n)-i64(1)); i >= (i64)(a); i--) #define all(v) (v).begin(), (v).end() #define rall(v) (v).rbegin(), (v).rend() /* macro end */ /* template */ namespace ebi { #ifdef LOCAL #define debug(...) \ std::cerr << "LINE: " << __LINE__ << " [" << #__VA_ARGS__ << "]:", \ debug_out(__VA_ARGS__) #else #define debug(...) #endif void debug_out() { std::cerr << std::endl; } template <typename Head, typename... Tail> void debug_out(Head h, Tail... t) { std::cerr << " " << h; if (sizeof...(t) > 0) std::cout << " :"; debug_out(t...); } template <typename T1, typename T2> std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa) { return os << pa.first << " " << pa.second; } template <typename T1, typename T2> std::istream &operator>>(std::istream &os, std::pair<T1, T2> &pa) { return os >> pa.first >> pa.second; } template <typename T> std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec) { for (std::size_t i = 0; i < vec.size(); i++) os << vec[i] << (i + 1 == vec.size() ? "" : " "); return os; } template <typename T> std::istream &operator>>(std::istream &os, std::vector<T> &vec) { for (T &e : vec) std::cin >> e; return os; } template <typename T> std::ostream &operator<<(std::ostream &os, const std::optional<T> &opt) { if (opt) { os << opt.value(); } else { os << "invalid value"; } return os; } using std::size_t; using i32 = std::int32_t; using u32 = std::uint32_t; using i64 = std::int64_t; using u64 = std::uint64_t; using i128 = __int128_t; using u128 = __uint128_t; template <class T, T init> auto make_vector(int n) { return std::vector<T>(n, init); } template <class T, T init, typename Head, typename... Tail> auto make_vector(Head n, Tail... ts) { return std::vector(n, make_vector<T, init>(ts...)); } template <class T> inline bool chmin(T &a, T b) { if (a > b) { a = b; return true; } return false; } template <class T> inline bool chmax(T &a, T b) { if (a < b) { a = b; return true; } return false; } template <class T> T pow(T x, i64 n) { T res = 1; while (n > 0) { if (n & 1) res = res * x; x = x * x; n >>= 1; } return res; } template <class T> T mod_pow(T x, i64 n, i64 mod) { T res = 1; while (n > 0) { if (n & 1) res = (res * x) % mod; x = (x * x) % mod; n >>= 1; } return res; } template <class T> T scan() { T val; std::cin >> val; return val; } template <class T> struct Edge { int to; T cost; Edge(int _to, T _cost = 1) : to(_to), cost(_cost) {} }; template <class T> struct Graph : std::vector<std::vector<Edge<T>>> { using std::vector<std::vector<Edge<T>>>::vector; void add_edge(int u, int v, T w, bool directed = false) { (*this)[u].emplace_back(v, w); if (directed) return; (*this)[v].emplace_back(u, w); } }; struct graph : std::vector<std::vector<int>> { using std::vector<std::vector<int>>::vector; void add_edge(int u, int v, bool directed = false) { (*this)[u].emplace_back(v); if (directed) return; (*this)[v].emplace_back(u); } }; constexpr i64 LNF = std::numeric_limits<i64>::max() / 4; constexpr int INF = std::numeric_limits<int>::max() / 2; const std::vector<int> dy = {1, 0, -1, 0, 1, 1, -1, -1}; const std::vector<int> dx = {0, 1, 0, -1, 1, -1, 1, -1}; } // namespace ebi #line 2 "tree/lowest_common_ancestor.hpp" #line 4 "tree/lowest_common_ancestor.hpp" #line 2 "data_structure/sparse_table.hpp" #line 4 "data_structure/sparse_table.hpp" /* reference: https://scrapbox.io/data-structures/Sparse_Table */ namespace ebi { template <class Band, Band (*op)(Band, Band)> struct sparse_table { public: sparse_table() = default; sparse_table(const std::vector<Band> &a) : n(a.size()) { table = std::vector(std::__lg(n) + 1, std::vector<Band>(n)); for (int i = 0; i < n; i++) { table[0][i] = a[i]; } for (int k = 1; (1 << k) <= n; k++) { for (int i = 0; i + (1 << k) <= n; i++) { table[k][i] = op(table[k - 1][i], table[k - 1][i + (1 << (k - 1))]); } } } void build(const std::vector<Band> &a) { n = (int)a.size(); table = std::vector(std::__lg(n) + 1, std::vector<Band>(n)); for (int i = 0; i < n; i++) { table[0][i] = a[i]; } for (int k = 1; (1 << k) <= n; k++) { for (int i = 0; i + (1 << k) <= n; i++) { table[k][i] = op(table[k - 1][i], table[k - 1][i + (1 << (k - 1))]); } } } // [l, r) Band fold(int l, int r) { int k = std::__lg(r - l); return op(table[k][l], table[k][r - (1 << k)]); } private: int n; std::vector<std::vector<Band>> table; }; } // namespace ebi #line 6 "tree/lowest_common_ancestor.hpp" namespace ebi { namespace internal_lca { std::pair<int, int> op(std::pair<int, int> a, std::pair<int, int> b) { return a.second < b.second ? a : b; } } // namespace internal_lca struct lowest_common_ancestor { public: lowest_common_ancestor(const std::vector<std::vector<int>> &gh, int root = 0) : n(gh.size()), id(n), depth(n) { auto dfs = [&](auto &&self, int v, int par = -1, int d = 0) -> void { id[v] = int(vs.size()); depth[v] = d; vs.emplace_back(v, d); for (const auto &nv : gh[v]) if (nv != par) { self(self, nv, v, d + 1); vs.emplace_back(v, d); } }; dfs(dfs, root); st.build(vs); } int lca(int u, int v) { int l = id[u], r = id[v]; if (r < l) std::swap(l, r); return st.fold(l, r + 1).first; } int distance(int u, int v) { int w = lca(u, v); return depth[u] + depth[v] - 2 * depth[w]; } private: int n; std::vector<int> id, depth; std::vector<std::pair<int, int>> vs; sparse_table<std::pair<int, int>, internal_lca::op> st; }; } // namespace ebi #line 2 "tree/level_ancestor.hpp" #line 6 "tree/level_ancestor.hpp" namespace ebi { struct level_ancestor { private: int n; std::vector<int> in; std::vector<int> inv_in; std::vector<int> depths; std::vector<std::vector<int>> s; public: level_ancestor(const std::vector<std::vector<int>> &gh, int root = 0) : n(gh.size()), in(n), inv_in(n), depths(n) { int cnt = 0; int max = 0; auto dfs = [&](auto &&self, int v, int par = -1) -> void { inv_in[cnt] = v; in[v] = cnt++; max = std::max(max, depths[v]); for (auto nv : gh[v]) if (nv != par) { depths[nv] = depths[v] + 1; self(self, nv, v); } }; dfs(dfs, root); s.resize(max + 1); for (int i = 0; i < n; i++) { int u = inv_in[i]; s[depths[u]].emplace_back(i); } } int query(int u, int k) const { int m = depths[u] - k; assert(m >= 0); return inv_in[*std::prev( std::upper_bound(s[m].begin(), s[m].end(), in[u]))]; } int depth(int u) const { return depths[u]; } }; } // namespace ebi #line 192 "a.cpp" namespace ebi { void main_() { int n,q; std::cin >> n >> q; graph g(n); rep(i,0,n-1) { int a,b; std::cin >> a >> b; a--; b--; g.add_edge(a, b); } lowest_common_ancestor lca(g); level_ancestor la(g); std::vector<std::map<int,int>> dp(n); std::vector<int> sz(n, 1); auto dfs = [&](auto &&self, int v, int par = -1) -> void { for(auto nv: g[v]) { if(nv == par) continue; self(self, nv, v); sz[v] += sz[nv]; } }; std::vector<int> sum(n, 1); auto rerooting = [&](auto &&self, int v, int par = -1, int val = -1) -> void { if(par != -1) { dp[v][par] = val; sum[v] += val; } for(auto nv: g[v]) { if(nv == par) continue; self(self, nv, v, n - sz[nv]); dp[v][nv] = sz[nv]; sum[v] += sz[nv]; } }; dfs(dfs, 0); rerooting(rerooting, 0); while(q--) { int s,t; std::cin >> s >> t; s--; t--; int d = lca.distance(s, t); if(d % 2 == 1) { std::cout << "0\n"; } else { auto jump_k = [&](int s, int t, int k) -> int { int m = lca.lca(s, t); int d = lca.distance(s, t); if(d < k) return -1; int v; if(k <= lca.distance(s, m)) { v = la.query(s, k); } else { k = d - k; assert(k <= lca.distance(m, t)); v = la.query(t, k); } return v; }; int mid = jump_k(s, t, d/2); int l = jump_k(s, t, d/2 - 1); int r = jump_k(t, s, d/2 - 1); int ans = sum[mid] - dp[mid][l] - dp[mid][r]; std::cout << ans << '\n'; } } } } // namespace ebi int main() { std::cout << std::fixed << std::setprecision(15); std::cin.tie(nullptr); std::ios::sync_with_stdio(false); int t = 1; // std::cin >> t; while (t--) { ebi::main_(); } return 0; }