結果
問題 | No.2337 Equidistant |
ユーザー |
|
提出日時 | 2023-06-02 22:01:57 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 2,330 ms / 4,000 ms |
コード長 | 3,588 bytes |
コンパイル時間 | 218 ms |
コンパイル使用メモリ | 82,300 KB |
実行使用メモリ | 193,168 KB |
最終ジャッジ日時 | 2024-12-28 17:57:58 |
合計ジャッジ時間 | 27,944 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 1 |
other | AC * 28 |
ソースコード
import sys, time, randomfrom collections import deque, Counter, defaultdictinput = lambda: sys.stdin.readline().rstrip()ii = lambda: int(input())mi = lambda: map(int, input().split())li = lambda: list(mi())inf = 2 ** 63 - 1mod = 998244353import sysclass LcaDoubling:"""links[v] = { u1, u2, ... } (u:隣接頂点, 親は含まない)というグラフ情報から、ダブリングによるLCAを構築。任意の2頂点のLCAを取得できるようにする"""def __init__(self, n, links, root=0):self.depths = [-1] * nprev_ancestors = self._init_dfs(n, links, root)self.ancestors = [prev_ancestors]max_depth = max(self.depths)d = 1while d < max_depth:next_ancestors = [prev_ancestors[p] for p in prev_ancestors]self.ancestors.append(next_ancestors)d <<= 1prev_ancestors = next_ancestorsdef _init_dfs(self, n, links, root):q = [root]direct_ancestors = [-1] * (n + 1) # 頂点数より1個長くし、存在しないことを-1で表す。末尾(-1)要素は常に-1self.depths[root] = 0while q:u = q.pop()for v in links[u]:if self.depths[v] != -1:continuedirect_ancestors[v] = uself.depths[v] = self.depths[u] + 1links[v].discard(u)q.append(v)return direct_ancestorsdef get_lca(self, u, v):du, dv = self.depths[u], self.depths[v]if du > dv:u, v = v, udu, dv = dv, dutu = utv = self.upstream(v, dv - du)if u == tv:return ufor k in range(du.bit_length() - 1, -1, -1):mu = self.ancestors[k][tu]mv = self.ancestors[k][tv]if mu != mv:tu = mutv = mvlca = self.ancestors[0][tu]assert lca == self.ancestors[0][tv]return lcadef upstream(self, v, k):i = 0while k:if k & 1:v = self.ancestors[i][v]k >>= 1i += 1return vdef jump(self, u: int, v: int, i: int) -> int:""" uからvに向けて進んだパスのi番目(0-indexed)の頂点を得る。パス長が足りない場合は-1 """c = self.get_lca(u, v)du = self.depths[u]dv = self.depths[v]dc = self.depths[c]path_len = du - dc + dv - dcif path_len < i:return -1if du - dc >= i:return self.upstream(u, i)return self.upstream(v, path_len - i)n, q = mi()graph = [set() for _ in range(n)]for _ in range(n - 1):u, v = mi()u -= 1; v -= 1graph[u].add(v)graph[v].add(u)L = LcaDoubling(n, graph)def size_of_subtree(s, t):if L.depths[s] < L.depths[t]:return subt[t]else:return n - subt[s]p = list(range(n))p.sort(key = lambda x: L.depths[x], reverse=True)subt = [0] * nfor v in p:for to in graph[v]:if L.depths[to] > L.depths[v]:subt[v] += subt[to]subt[v] += 1for _ in range(q):s, t = mi()s -= 1; t -= 1x = L.get_lca(s, t)l = L.depths[s] + L.depths[t] - 2 * L.depths[x]if l % 2 == 1:print(0)else:u = L.jump(s, t, l // 2)s1 = L.jump(u, s, 1)t1 = L.jump(u, t, 1)ans = n - size_of_subtree(u, s1) - size_of_subtree(u, t1)print(ans)