結果
問題 | No.2337 Equidistant |
ユーザー |
![]() |
提出日時 | 2023-06-02 21:35:41 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 291 ms / 4,000 ms |
コード長 | 8,438 bytes |
コンパイル時間 | 1,680 ms |
コンパイル使用メモリ | 135,696 KB |
最終ジャッジ日時 | 2025-02-13 17:48:46 |
ジャッジサーバーID (参考情報) |
judge2 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 1 |
other | AC * 28 |
ソースコード
#ifndef LOCAL#define FAST_IO#endif// ============#include <algorithm>#include <array>#include <bitset>#include <cassert>#include <cmath>#include <iomanip>#include <iostream>#include <list>#include <map>#include <numeric>#include <queue>#include <random>#include <set>#include <stack>#include <string>#include <tuple>#include <unordered_map>#include <unordered_set>#include <utility>#include <vector>#define OVERRIDE(a, b, c, d, ...) d#define REP2(i, n) for (i32 i = 0; i < (i32)(n); ++i)#define REP3(i, m, n) for (i32 i = (i32)(m); i < (i32)(n); ++i)#define REP(...) OVERRIDE(__VA_ARGS__, REP3, REP2)(__VA_ARGS__)#define PER(i, n) for (i32 i = (i32)(n) - 1; i >= 0; --i)#define ALL(x) begin(x), end(x)using namespace std;using u32 = unsigned int;using u64 = unsigned long long;using i32 = signed int;using i64 = signed long long;using f64 = double;using f80 = long double;template <typename T>using Vec = vector<T>;template <typename T>bool chmin(T &x, const T &y) {if (x > y) {x = y;return true;}return false;}template <typename T>bool chmax(T &x, const T &y) {if (x < y) {x = y;return true;}return false;}#ifdef INT128using u128 = __uint128_t;using i128 = __int128_t;istream &operator>>(istream &is, i128 &x) {i64 v;is >> v;x = v;return is;}ostream &operator<<(ostream &os, i128 x) {os << (i64)x;return os;}istream &operator>>(istream &is, u128 &x) {u64 v;is >> v;x = v;return is;}ostream &operator<<(ostream &os, u128 x) {os << (u64)x;return os;}#endif[[maybe_unused]] constexpr i32 INF = 1000000100;[[maybe_unused]] constexpr i64 INF64 = 3000000000000000100;struct SetUpIO {SetUpIO() {#ifdef FAST_IOios::sync_with_stdio(false);cin.tie(nullptr);#endifcout << fixed << setprecision(15);}} set_up_io;// ============#ifdef DEBUGF#else#define DBG(x) (void)0#endif// ============#include <algorithm>#include <cassert>#include <utility>#include <vector>class HeavyLightDecomposition {std::vector<int> siz;std::vector<int> par;std::vector<int> hea;std::vector<int> in;std::vector<int> out;std::vector<int> dep;std::vector<int> rev;template <typename G>void dfs1(G &g, int v) {if (!g[v].empty() && (int) g[v][0] == par[v]) {std::swap(g[v][0], g[v].back());}for (auto &e : g[v]) {int u = (int)e;if (u != par[v]) {par[u] = v;dfs1(g, u);siz[v] += siz[u];if (siz[u] > siz[(int) g[v][0]]) {std::swap(g[v][0], e);}}}}template <typename G>void dfs2(const G &g, int v, int &time) {in[v] = time;rev[time++] = v;for (auto &e : g[v]) {int u = (int)e;if (u == par[v]) {continue;}if (u == (int) g[v][0]) {hea[u] = hea[v];} else {hea[u] = u;}dep[u] = dep[v] + 1;dfs2(g, u, time);}out[v] = time;}public:template <typename G>HeavyLightDecomposition(G &g, int root = 0) :siz(g.size(), 1),par(g.size(), root),hea(g.size(), root),in(g.size(), 0),out(g.size(), 0),dep(g.size(), 0),rev(g.size(), 0) {assert(root >= 0 && root < (int) g.size());dfs1(g, root);int time = 0;dfs2(g, root, time);}int subtree_size(int v) const {assert(v >= 0 && v < (int) siz.size());return siz[v];}int parent(int v) const {assert(v >= 0 && v < (int) par.size());return par[v];}int in_time(int v) const {assert(v >= 0 && v < (int) in.size());return in[v];}int out_time(int v) const {assert(v >= 0 && v < (int) out.size());return out[v];}int depth(int v) const {assert(v >= 0 && v < (int) dep.size());return dep[v];}int time_to_vertex(int t) const {assert(t >= 0 && t < (int) rev.size());return rev[t];}int la(int v, int k) const {assert(v >= 0 && v < (int) dep.size());assert(k >= 0);if (k > dep[v]) {return -1;}while (true) {int u = hea[v];if (in[u] + k <= in[v]) {return rev[in[v] - k];}k -= in[v] - in[u] + 1;v = par[u];}return 0;}int forward(int v, int dst) const {assert(v >= 0 && v < (int) dep.size());assert(dst >= 0 && dst < (int) dep.size());assert(v != dst);int l = lca(v, dst);if (l == v) {return la(dst, dep[dst] - dep[v] - 1);} else {return par[v];}}int lca(int u, int v) const {assert(u >= 0 && u < (int) dep.size());assert(v >= 0 && v < (int) dep.size());while (u != v) {if (in[u] > in[v]) {std::swap(u, v);}if (hea[u] == hea[v]) {v = u;} else {v = par[hea[v]];}}return u;}int dist(int u, int v) const {assert(u >= 0 && u < (int) dep.size());assert(v >= 0 && v < (int) dep.size());return dep[u] + dep[v] - 2 * dep[lca(u, v)];}std::vector<std::pair<int, int>> path(int u, int v, bool edge) const {assert(u >= 0 && u < (int) dep.size());assert(v >= 0 && v < (int) dep.size());std::vector<std::pair<int, int>> fromu, fromv;bool rev = false;while (true) {if (u == v && edge) {break;}if (in[u] > in[v]) {std::swap(u, v);std::swap(fromu, fromv);rev ^= true;}if (hea[u] == hea[v]) {fromv.emplace_back(in[v], in[u] + (int)edge);v = u;break;} else {fromv.emplace_back(in[v], in[hea[v]]);v = par[hea[v]];}}if (rev) {std::swap(fromu, fromv);}std::reverse(fromv.begin(), fromv.end());fromu.reserve(fromv.size());for (auto [x, y] : fromv) {fromu.emplace_back(y, x);}return fromu;}int jump(int u, int v, int k) const {assert(u >= 0 && u < (int) dep.size());assert(v >= 0 && v < (int) dep.size());assert(k >= 0);int l = lca(u, v);int dis = dep[u] + dep[v] - 2 * dep[l];if (k > dis) {return -1;}if (k <= dep[u] - dep[l]) {return la(u, k);} else {return la(v, dis - k);}}int meet(int u, int v, int w) const {return lca(u, v) ^ lca(v, w) ^ lca(w, u);}};// ============int main() {i32 n, q;cin >> n >> q;Vec<Vec<i32>> g(n);REP(i, n - 1) {i32 u, v;cin >> u >> v;--u;--v;g[u].push_back(v);g[v].push_back(u);}HeavyLightDecomposition hld(g);while (q--) {i32 s, t;cin >> s >> t;--s;--t;i32 d = hld.dist(s, t);if (d % 2 == 0) {i32 lca = hld.lca(s, t);i32 s_l = hld.depth(s) - hld.depth(lca);if (s_l == d / 2) {i32 s_ = hld.forward(lca, s);i32 t_ = hld.forward(lca, t);cout << n - hld.subtree_size(s_) - hld.subtree_size(t_) << '\n';} else {if (s_l > d / 2) {swap(s, t);s_l = d - s_l;}i32 mid = hld.la(t, d / 2);i32 t_ = hld.forward(mid, t);i32 s_side = n - hld.subtree_size(mid);i32 t_size = hld.subtree_size(t_);cout << n - s_side - t_size << '\n';}} else {cout << 0 << '\n';}}}