結果
問題 | No.399 動的な領主 |
ユーザー |
![]() |
提出日時 | 2025-03-26 15:59:05 |
言語 | PyPy3 (7.3.15) |
結果 |
TLE
|
実行時間 | - |
コード長 | 5,830 bytes |
コンパイル時間 | 169 ms |
コンパイル使用メモリ | 82,556 KB |
実行使用メモリ | 145,480 KB |
最終ジャッジ日時 | 2025-03-26 15:59:51 |
合計ジャッジ時間 | 5,595 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 6 TLE * 1 -- * 12 |
ソースコード
import sysfrom sys import stdinsys.setrecursionlimit(1 << 25)def main():input = sys.stdin.read().split()ptr = 0N = int(input[ptr])ptr +=1# Build adjacency listadj = [[] for _ in range(N+1)]for _ in range(N-1):u = int(input[ptr])v = int(input[ptr+1])adj[u].append(v)adj[v].append(u)ptr +=2# Compute parent, depth, size, heavy child using iterative DFSparent = [0]*(N+1)depth = [0]*(N+1)size = [1]*(N+1)heavy = [-1]*(N+1)# First pass to compute parent and depth using BFSfrom collections import dequeq = deque()root = 1q.append(root)parent[root] = -1depth[root] = 0while q:v = q.popleft()for u in adj[v]:if parent[v] != u:parent[u] = vdepth[u] = depth[v] +1q.append(u)# Second pass to compute size and heavy child using iterative post-order traversalstack = [(root, False)]order = []while stack:v, visited = stack.pop()if visited:order.append(v)max_size = -1for u in adj[v]:if u != parent[v]:size[v] += size[u]if size[u] > max_size:max_size = size[u]heavy[v] = uelse:stack.append((v, True))# Push children in reverse order to process them in orderfor u in reversed(adj[v]):if u != parent[v]:stack.append((u, False))# Assign in-time and head using iterative DFSin_time = [0]*(N+1)head = [0]*(N+1)current_time =0stack = [(root, root)]while stack:v, h = stack.pop()head[v] = hin_time[v] = current_timecurrent_time +=1# Push children, heavy child lastfor u in adj[v]:if u != parent[v] and u != heavy[v]:stack.append((u, u))if heavy[v] != -1:stack.append((heavy[v], h))# Build LCA binary lifting tableLOG = 20up = [[-1]*(N+1) for _ in range(LOG)]up[0] = parentfor k in range(1, LOG):for v in range(1, N+1):if up[k-1][v] != -1:up[k][v] = up[k-1][up[k-1][v]]else:up[k][v] = -1def lca(u, v):if depth[u] < depth[v]:u, v = v, u# Bring u up to depth of vfor k in range(LOG-1, -1, -1):if depth[u] - (1 << k) >= depth[v]:u = up[k][u]if u == v:return ufor k in range(LOG-1, -1, -1):if up[k][u] != up[k][v]:u = up[k][u]v = up[k][v]return up[0][u]# Segment Tree with Lazy Propagationclass SegmentTree:def __init__(self, size):self.n = 1while self.n < size:self.n <<=1self.size = self.nself.tree = [0]*(2*self.n)self.lazy = [0]*(2*self.n)def push(self, node, l, r):if self.lazy[node] !=0:mid = (l + r)//2left_node = node *2right_node = node*2 +1# Update left childself.tree[left_node] += self.lazy[node] * (mid - l +1)self.lazy[left_node] += self.lazy[node]# Update right childself.tree[right_node] += self.lazy[node] * (r - mid)self.lazy[right_node] += self.lazy[node]# Clear lazyself.lazy[node] =0def update_range(self, a, b, val, node=1, l=0, r=None):if r is None:r = self.n -1if a > r or b < l:returnif a <= l and r <= b:self.tree[node] += val * (r - l +1)self.lazy[node] += valreturnself.push(node, l, r)mid = (l + r)//2self.update_range(a, b, val, node*2, l, mid)self.update_range(a, b, val, node*2+1, mid+1, r)self.tree[node] = self.tree[node*2] + self.tree[node*2+1]def query_range(self, a, b, node=1, l=0, r=None):if r is None:r = self.n -1if a > r or b < l:return 0if a <= l and r <= b:return self.tree[node]self.push(node, l, r)mid = (l + r)//2return self.query_range(a, b, node*2, l, mid) + self.query_range(a, b, node*2+1, mid+1, r)seg = SegmentTree(N)def query_path(u, v):res =0while head[u] != head[v]:if depth[head[u]] < depth[head[v]]:u, v = v, ures += seg.query_range(in_time[head[u]], in_time[u])u = parent[head[u]]if depth[u] > depth[v]:u, v = v, ures += seg.query_range(in_time[u], in_time[v])return resdef update_path(u, v, val):while head[u] != head[v]:if depth[head[u]] < depth[head[v]]:u, v = v, useg.update_range(in_time[head[u]], in_time[u], val)u = parent[head[u]]if depth[u] > depth[v]:u, v = v, useg.update_range(in_time[u], in_time[v], val)Q = int(input[ptr])ptr +=1ans =0for _ in range(Q):A = int(input[ptr])B = int(input[ptr+1])ptr +=2c = lca(A, B)distance = depth[A] + depth[B] - 2 * depth[c]nodes = distance +1sum_val = query_path(A, B)ans += sum_val + nodesupdate_path(A, B, 1)print(ans)if __name__ == '__main__':main()