結果
| 問題 |
No.2337 Equidistant
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2023-06-02 23:22:59 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 1,541 ms / 4,000 ms |
| コード長 | 10,626 bytes |
| コンパイル時間 | 2,875 ms |
| コンパイル使用メモリ | 163,592 KB |
| 最終ジャッジ日時 | 2025-02-13 20:45:26 |
|
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 28 |
ソースコード
#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;
}