#line 1 "a.cpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* 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 void debug_out(Head h, Tail... t) { std::cerr << " " << h; if (sizeof...(t) > 0) std::cout << " :"; debug_out(t...); } template std::ostream &operator<<(std::ostream &os, const std::pair &pa) { return os << pa.first << " " << pa.second; } template std::istream &operator>>(std::istream &os, std::pair &pa) { return os >> pa.first >> pa.second; } template std::ostream &operator<<(std::ostream &os, const std::vector &vec) { for (std::size_t i = 0; i < vec.size(); i++) os << vec[i] << (i + 1 == vec.size() ? "" : " "); return os; } template std::istream &operator>>(std::istream &os, std::vector &vec) { for (T &e : vec) std::cin >> e; return os; } template std::ostream &operator<<(std::ostream &os, const std::optional &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 auto make_vector(int n) { return std::vector(n, init); } template auto make_vector(Head n, Tail... ts) { return std::vector(n, make_vector(ts...)); } template inline bool chmin(T &a, T b) { if (a > b) { a = b; return true; } return false; } template inline bool chmax(T &a, T b) { if (a < b) { a = b; return true; } return false; } template 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 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 T scan() { T val; std::cin >> val; return val; } template struct Edge { int to; T cost; Edge(int _to, T _cost = 1) : to(_to), cost(_cost) {} }; template struct Graph : std::vector>> { using std::vector>>::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> { using std::vector>::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::max() / 4; constexpr int INF = std::numeric_limits::max() / 2; const std::vector dy = {1, 0, -1, 0, 1, 1, -1, -1}; const std::vector 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 struct sparse_table { public: sparse_table() = default; sparse_table(const std::vector &a) : n(a.size()) { table = std::vector(std::__lg(n) + 1, std::vector(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 &a) { n = (int)a.size(); table = std::vector(std::__lg(n) + 1, std::vector(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> table; }; } // namespace ebi #line 6 "tree/lowest_common_ancestor.hpp" namespace ebi { namespace internal_lca { std::pair op(std::pair a, std::pair b) { return a.second < b.second ? a : b; } } // namespace internal_lca struct lowest_common_ancestor { public: lowest_common_ancestor(const std::vector> &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 id, depth; std::vector> vs; sparse_table, 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 in; std::vector inv_in; std::vector depths; std::vector> s; public: level_ancestor(const std::vector> &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> dp(n); std::vector 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 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; }