結果
| 問題 |
No.2296 Union Path Query (Hard)
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2023-03-16 05:51:24 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 3,797 bytes |
| コンパイル時間 | 318 ms |
| コンパイル使用メモリ | 81,920 KB |
| 実行使用メモリ | 340,640 KB |
| 最終ジャッジ日時 | 2024-11-23 04:36:19 |
| 合計ジャッジ時間 | 192,009 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 15 WA * 7 RE * 4 TLE * 19 |
ソースコード
from sys import stdin
from collections import deque
class UnionFind():
def __init__(self, n):
self.parent_or_size = [-1] * n
self.G = [[] for i in range(n)]
self.E = [[] for i in range(n)]
self.depth = [0] * n
self.dp = [0] * n
self.log_table = [0] * n
self.diameter = [0] * n
self.diameter_vertex = [0] * (2 * n)
self.parent = [[-1] * n for i in range(18)]
self.que = deque()
for i in range(n):
self.diameter_vertex[i << 1] = i
self.diameter_vertex[(i << 1) + 1] = i
for i in range(2, n):
self.log_table[i] = self.log_table[i >> 1] + 1
def leader(self, x):
return x if self.parent_or_size[x] < 0 else self.parent_or_size[x]
def merge(self, u, v, w):
x, y = self.leader(u), self.leader(v)
if -self.parent_or_size[x] < -self.parent_or_size[y]:
x, y = y, x
u, v = v, u
self.parent_or_size[x] += self.parent_or_size[y]
self.G[u].append(v)
self.G[v].append(u)
self.E[v].append(w)
self.E[u].append(w)
self.update_parent(v, u, w)
self.que.append(v)
while len(self.que):
v = self.que.popleft()
self.parent_or_size[v] = x
for i in range(len(self.G[v])):
if self.G[v][i] == self.parent[0][v]: continue
self.update_parent(self.G[v][i], v, self.E[v][i])
self.que.append(self.G[v][i])
self.update_diameter(x, y)
def update_parent(self, v, par, w):
logv = self.log_table[max(self.depth[v], self.depth[par] + 1)]
self.depth[v] = self.depth[par] + 1
self.dp[v] = self.dp[par] + w
self.parent[0][v] = par
for i in range(logv):
self.parent[i + 1][v] = -1 if self.parent[i][v] == -1 else self.parent[i][self.parent[i][v]]
def update_diameter(self, x, y):
mx, v, u = 0, 0, 0
v1, v2 = self.diameter_vertex[2 * x], self.diameter_vertex[2 * x + 1]
v3, v4 = self.diameter_vertex[2 * y], self.diameter_vertex[2 * y + 1]
if self.diameter[x] >= self.diameter[y]:
mx, u, v = self.diameter[x], v1, v2
else:
mx, u, v = self.diameter[y], v3, v4
d = self.dist(v1, v3)
if d > mx: mx, u, v = d, v1, v3
d = self.dist(v1, v4)
if d > mx: mx, u, v = d, v1, v4
d = self.dist(v2, v3)
if d > mx: mx, u, v = d, v2, v3
d = self.dist(v2, v4)
if d > mx: mx, u, v = d, v2, v4
self.diameter[x], self.diameter_vertex[2 * x], self.diameter_vertex[2 * x + 1] = mx, u, v
def dist(self, u, v):
if self.leader(u) != self.leader(v): return -1
if self.depth[u] > self.depth[v]: u, v = v, u
res = self.dp[u] + self.dp[v]
d = self.depth[v] - self.depth[u]
while d:
v = self.parent[self.log_table[d & -d]][v]
d -= d & -d
if u == v: return res - 2 * self.dp[v]
for i in range(self.log_table[d], -1,-1):
if self.parent[i][v] != self.parent[i][u]:
u = self.parent[i][u]
v = self.parent[i][v]
return res - 2 * self.dp[self.parent[0][v]]
N, X, Q = map(int, stdin.readline().split())
uf = UnionFind(N)
for _ in range(Q):
query = list(map(int, stdin.readline().split()))
if query[0] == 1:
uf.merge(X, query[1], query[2])
elif query[0] == 2:
d = uf.dist(query[1], query[2])
print(d)
if d != -1:
X += d
X %= N
elif query[0] == 3:
print(uf.diameter[uf.leader(query[1])])
else:
X += query[1]
if X >= N: X -= N