結果
| 問題 |
No.900 aδδitivee
|
| コンテスト | |
| ユーザー |
brthyyjp
|
| 提出日時 | 2021-01-24 01:19:17 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 685 ms / 2,000 ms |
| コード長 | 5,692 bytes |
| コンパイル時間 | 200 ms |
| コンパイル使用メモリ | 82,876 KB |
| 実行使用メモリ | 115,248 KB |
| 最終ジャッジ日時 | 2025-01-02 00:31:42 |
| 合計ジャッジ時間 | 15,966 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 27 |
ソースコード
class HLD:
def __init__(self, g):
self.g = g
self.n = len(g)
self.parent = [-1]*self.n
self.size = [1]*self.n
self.head = [0]*self.n
self.preorder = [0]*self.n
self.k = 0
for v in range(self.n):
if self.parent[v] == -1:
self.dfs_pre(v)
self.dfs_hld(v)
def dfs_pre(self, v):
g = self.g
stack = [v]
order = [v]
while stack:
v = stack.pop()
for u in g[v]:
if self.parent[v] == u:
continue
self.parent[u] = v
stack.append(u)
order.append(u)
# 隣接リストの左端: heavyな頂点への辺
# 隣接リストの右端: 親への辺
while order:
v = order.pop()
child_v = g[v]
if len(child_v) and child_v[0] == self.parent[v]:
child_v[0], child_v[-1] = child_v[-1], child_v[0]
for i, u in enumerate(child_v):
if u == self.parent[v]:
continue
self.size[v] += self.size[u]
if self.size[u] > self.size[child_v[0]]:
child_v[i], child_v[0] = child_v[0], child_v[i]
def dfs_hld(self, v):
stack = [v]
while stack:
v = stack.pop()
self.preorder[v] = self.k
self.k += 1
top = self.g[v][0]
# 隣接リストを逆順に見ていく(親 > lightな頂点への辺 > heavyな頂点 (top))
# 連結成分が連続するようにならべる
for u in reversed(self.g[v]):
if u == self.parent[v]:
continue
if u == top:
self.head[u] = self.head[v]
else:
self.head[u] = u
stack.append(u)
def for_each(self, u, v):
# [u, v]上の頂点集合の区間を列挙
while True:
if self.preorder[u] > self.preorder[v]:
u, v = v, u
l = max(self.preorder[self.head[v]], self.preorder[u])
r = self.preorder[v]
yield l, r # [l, r]
if self.head[u] != self.head[v]:
v = self.parent[self.head[v]]
else:
return
def for_each_edge(self, u, v):
# [u, v]上の辺集合の区間列挙
# 辺の情報は子の頂点に
while True:
if self.preorder[u] > self.preorder[v]:
u, v = v, u
if self.head[u] != self.head[v]:
yield self.preorder[self.head[v]], self.preorder[v]
v = self.parent[self.head[v]]
else:
if u != v:
yield self.preorder[u]+1, self.preorder[v]
break
def subtree(self, v):
# 頂点vの部分木の頂点集合の区間 [l, r)
l = self.preorder[v]
r = self.preorder[v]+self.size[v]
return l, r
def lca(self, u, v):
# 頂点u, vのLCA
while True:
if self.preorder[u] > self.preorder[v]:
u, v = v, u
if self.head[u] == self.head[v]:
return u
v = self.parent[self.head[v]]
class BIT:
def __init__(self, n):
self.n = n
self.bit = [0]*(self.n+1) # 1-indexed
def init(self, init_val):
for i, v in enumerate(init_val):
self.add(i, v)
def add(self, i, x):
# i: 0-indexed
i += 1 # to 1-indexed
while i <= self.n:
self.bit[i] += x
i += (i & -i)
def sum(self, i, j):
# return sum of [i, j)
# i, j: 0-indexed
return self._sum(j) - self._sum(i)
def _sum(self, i):
# return sum of [0, i)
# i: 0-indexed
res = 0
while i > 0:
res += self.bit[i]
i -= i & (-i)
return res
class RangeAddBIT:
def __init__(self, n):
self.n = n
self.bit1 = BIT(n)
self.bit2 = BIT(n)
def init(self, init_val):
self.bit2.init(init_val)
def add(self, l, r, x):
# add x to [l, r)
# l, r: 0-indexed
self.bit1.add(l, x)
self.bit1.add(r, -x)
self.bit2.add(l, -x*l)
self.bit2.add(r, x*r)
def sum(self, l, r):
# return sum of [l, r)
# l, r: 0-indexed
return self._sum(r) - self._sum(l)
def _sum(self, i):
# return sum of [0, i)
# i: 0-indexed
return self.bit1._sum(i)*i + self.bit2._sum(i)
import sys
import io, os
input = io.BytesIO(os.read(0,os.fstat(0).st_size)).readline
def main():
n = int(input())
edge = [[] for i in range(n)]
E = []
for i in range(n-1):
u, v, w = map(int, input().split())
edge[u].append(v)
edge[v].append(u)
E.append((u, v, w))
hld = HLD(edge)
bit = RangeAddBIT(n)
for u, v, w in E:
if hld.parent[u] == v:
bit.add(hld.preorder[u], hld.preorder[u]+1, w)
else:
bit.add(hld.preorder[v], hld.preorder[v]+1, w)
q = int(input())
for i in range(q):
temp = list(map(int, input().split()))
if temp[0] == 1:
a, x = temp[1], temp[2]
l, r = hld.subtree(a)
bit.add(l, r, x)
bit.add(hld.preorder[a], hld.preorder[a]+1, -x)
else:
b = temp[1]
ans = 0
for l, r in hld.for_each_edge(0, b):
ans += bit.sum(l, r+1)
print(ans)
if __name__ == '__main__':
main()
brthyyjp