結果

問題 No.399 動的な領主
ユーザー onakasuitacityonakasuitacity
提出日時 2023-05-06 10:01:45
言語 PyPy3
(7.3.15)
結果
TLE  
実行時間 -
コード長 4,821 bytes
コンパイル時間 240 ms
コンパイル使用メモリ 82,048 KB
実行使用メモリ 107,696 KB
最終ジャッジ日時 2024-05-02 23:48:14
合計ジャッジ時間 6,895 ms
ジャッジサーバーID
(参考情報)
judge2 / judge5
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 36 ms
58,752 KB
testcase_01 AC 38 ms
53,376 KB
testcase_02 AC 85 ms
76,288 KB
testcase_03 AC 78 ms
75,648 KB
testcase_04 AC 469 ms
81,568 KB
testcase_05 AC 1,383 ms
90,884 KB
testcase_06 TLE -
testcase_07 -- -
testcase_08 -- -
testcase_09 -- -
testcase_10 -- -
testcase_11 -- -
testcase_12 -- -
testcase_13 -- -
testcase_14 -- -
testcase_15 -- -
testcase_16 -- -
testcase_17 -- -
testcase_18 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

import sys
input = sys.stdin.buffer.readline

class LinkCutTree(object):
    def __init__(self, A, dot, e, compose, id, act):
        n = len(A)
        self._value = A[:]
        self._left = [-1] * n
        self._right = [-1] * n
        self._parent = [-1] * n
        self._size = [1] * n
        self._sum = A[:]
        self._reverse = [False] * n
        self._lazy = [id] * n
        self._dot, self._e, self._compose, self._id, self._act = dot, e, compose, id, act
    
    def _push(self, v):
        left, right = self._left, self._right
        if self._lazy[v] != self._id:
            lazy, compose, act = self._lazy, self._compose, self._act
            self._value[v] = act(lazy[v], self._value[v], 1)
            self._sum[v] = act(lazy[v], self._sum[v], self._size[v])
            if left[v] != -1:
                lazy[left[v]] = compose(lazy[left[v]], lazy[v])
            if right[v] != -1:
                lazy[right[v]] = compose(lazy[right[v]], lazy[v])
            lazy[v] = self._id
        if self._reverse[v]:
            reverse = self._reverse
            left[v], right[v] = right[v], left[v]
            if left[v] != -1:
                reverse[left[v]] ^= True
            if right[v] != -1:
                reverse[right[v]] ^= True
            reverse[v] = False
            return True
        return False
    
    def _update(self, v):
        left, right, size, sum = self._left, self._right, self._size, self._sum
        size[v] = 1
        sum[v] = self._value[v]
        if left[v] != -1:
            self._push(left[v])
            size[v] += size[left[v]]
            sum[v] = self._dot(sum[left[v]], sum[v])
        if right[v] != -1:
            self._push(right[v])
            size[v] += size[right[v]]
            sum[v] = self._dot(sum[v], sum[right[v]])
    
    def _rotate(self, v, p, d):
        left, right, parent = self._left, self._right, self._parent
        if d:
            left[p] = right[v]
            if right[v] != -1:
                parent[right[v]] = p
            right[v], parent[p] = p, v
        else:
            right[p] = left[v]
            if left[v] != -1:
                parent[left[v]] = p
            left[v], parent[p] = p, v
        self._update(p)
    
    def _splay(self, v):
        left, right, parent = self._left, self._right, self._parent
        push, rotate = self._push, self._rotate
        path, direction = [], []
        u = v
        while True:
            p = parent[u]
            if p == -1 or left[p] != u != right[p]:
                parent[v] = p
                break
            path.append(p)
            direction.append(u == left[p])
            u = p
        path.reverse()
        direction = [d ^ push(u) for u, d in zip(path, direction[::-1])]
        push(v)
        while len(path) >= 2:
            p, g = path.pop(), path.pop()
            dp, dg = direction.pop(), direction.pop()
            if dp == dg:
                rotate(p, g, dg)
                rotate(v, p, dp)
            else:
                rotate(v, p, dp)
                rotate(v, g, dg)
        if path:
            p = path.pop()
            d = direction.pop()
            rotate(v, p, d)

    def _expose(self, v):
        right, parent, splay = self._right, self._parent, self._splay
        prev, cur = -1, v
        while cur != -1:
            splay(cur)
            right[cur] = prev
            prev, cur = cur, parent[cur]
        splay(v)
        self._update(v)
        return prev
    
    def evert(self, v):
        self._expose(v)
        self._reverse[v] ^= True
    
    def lca(self, u, v):
        self._expose(u)
        return self._expose(v)
    
    def link(self, u, v):
        self.evert(u)
        self._parent[u] = v
    
    def cut(self, v):
        self._expose(v)
        self._parent[self._left[v]] = -1
        self._left[v] = -1
        self._update(v)
    
    def is_connected(self, u, v):
        if u == v:
            return True
        self._expose(u)
        self._expose(v)
        return self._parent[u] != -1
    
    def depth(self, v):
        self._expose(v)
        return self._size[v] - 1
    
    def act(self, u, v, f):
        self.evert(u)
        self._expose(v)
        self._lazy[v] = self._compose(self._lazy[v], f) 
    
    def sum(self, u, v):
        self.evert(u)
        self._expose(v)
        return self._sum[v]


from operator import add

N = int(input())
dot = add
e = 0
compose = add
id = 0
act = lambda f, val, size: val + f * size

tree = LinkCutTree([1] * N, dot, e, compose, id, act)
for _ in range(N - 1):
    u, v = map(int, input().split())
    u -= 1
    v -= 1
    tree.link(u, v)

ans = 0
Q = int(input())
for _ in range(Q):
    u, v = map(int, input().split())
    u -= 1
    v -= 1
    ans += tree.sum(u, v)
    tree.act(u, v, 1)

print(ans)
0