結果
問題 | No.2439 Fragile Apple Tree |
ユーザー |
|
提出日時 | 2023-08-12 01:59:09 |
言語 | PyPy3 (7.3.15) |
結果 |
WA
|
実行時間 | - |
コード長 | 13,413 bytes |
コンパイル時間 | 302 ms |
コンパイル使用メモリ | 82,760 KB |
実行使用メモリ | 234,380 KB |
最終ジャッジ日時 | 2024-11-22 12:45:15 |
合計ジャッジ時間 | 87,937 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 7 WA * 23 |
ソースコード
import sysinput = lambda :sys.stdin.readline()[:-1]ni = lambda :int(input())na = lambda :list(map(int,input().split()))yes = lambda :print("yes");Yes = lambda :print("Yes");YES = lambda : print("YES")no = lambda :print("no");No = lambda :print("No");NO = lambda : print("NO")#######################################################################"""Buggy! the output of practice_k becomes about 1/4."""from typing import Callable, List, TypeVarS = TypeVar("S")F = TypeVar("F")MOD = 998244353class LazySegmentTree:"""Lazy Segment TreeReferences:https://github.com/atcoder/ac-library/blob/master/atcoder/lazysegtree.hpp"""__slots__ = ["e","op","id","mapping","composition","_n","_log","_size","tree","lazy",]def __init__(self,a: List[S],e: S,op: Callable[[S, S], S],id_: F,mapping: Callable[[F, S], S],composition: Callable[[F, F], F],) -> None:self.e = eself.op = opself.id = id_self.mapping = mappingself.composition = compositionself._n = len(a)self._log = (self._n - 1).bit_length()self._size = 1 << self._logself.tree = [e] * self._size + a + [e] * (self._size - self._n)for i in range(self._size - 1, 0, -1):self._update(i)self.lazy = [id_] * self._sizedef _update(self, k: int) -> None:"""Update the value of a[k]."""self.tree[k] = self.op(self.tree[2 * k], self.tree[2 * k + 1])def _apply_all(self, k: int, f: F) -> None:self.tree[k] = self.mapping(f, self.tree[k])if k < self._size:self.lazy[k] = self.composition(f, self.lazy[k])def _push(self, k: int) -> None:self._apply_all(2 * k, self.lazy[k])self._apply_all(2 * k + 1, self.lazy[k])self.lazy[k] = self.iddef set(self, k: int, x: S) -> None:"""Assign x to a[k] in O(log n)."""assert 0 <= k < self._nk += self._sizefor i in range(self._log, 0, -1):self._push(k >> i)self.tree[k] = xwhile k:k >>= 1self._update(k)def get(self, k: int) -> S:"""Return a[k] in O(1)."""assert 0 <= k < self._nk += self._sizefor i in range(self._log, 0, -1):self._push(k >> i)return self.tree[k]def prod(self, l: int, r: int) -> S:"""Return op(a[l], ..., a[r - 1]). Return e, if l == r.Complexity: O(log n)"""assert 0 <= l <= r <= self._nif l == r:return self.el += self._sizer += self._sizefor i in range(self._log, 0, -1):if ((l >> i) << i) != l:self._push(l >> i)if ((r >> i) << i) != r:self._push(r >> i)sml, smr = self.e, self.ewhile l < r:if l & 1:sml = self.op(sml, self.tree[l])l += 1if r & 1:r -= 1smr = self.op(self.tree[r], smr)l >>= 1r >>= 1return self.op(sml, smr)def prod_all(self) -> S:"""Return op(a[0], ..., a[n - 1]. Return e if n == 0.Complexity: O(1)"""return self.tree[1]def apply(self, k: int, f: F) -> None:"""Apply a[p] = op_st(a[p], x) in O(log n)."""assert 0 <= k < self._nk += self._sizefor i in range(self._log, 0, -1):self._push(k >> i)self.tree[k] = self.mapping(f, self.tree[k])for i in range(1, self._log + 1):self._update(k >> i)def apply_range(self, l: int, r: int, f: F) -> None:"""Apply a[i] = op_st(a[i], x) for all i = l..r-1 in O(log n)."""assert 0 <= l <= r <= self._nif l == r:returnl += self._sizer += self._sizefor i in range(self._log, 0, -1):if ((l >> i) << i) != l:self._push(l >> i)if ((r >> i) << i) != r:self._push((r - 1) >> i)l_tmp, r_tmp = l, rwhile l < r:if l & 1:self._apply_all(l, f)l += 1if r & 1:r -= 1self._apply_all(r, f)l >>= 1r >>= 1l, r = l_tmp, r_tmpfor i in range(1, self._log + 1):if ((l >> i) << i) != l:self._update(l >> i)if ((r >> i) << i) != r:self._update((r - 1) >> i)def max_right(self, l: int, g: Callable[[S], bool]) -> int:"""Return an index r satisfying both:1. r = l or f(op(a[l], a[l + 1], ..., a[r - 1])) = true2. r = n or f(op(a[l], a[l + 1], ..., a[r])) = false.If f is monotone, this is the maximum r satisfying:f(op(a[l], a[l + 1], ..., a[r - 1])) = true.Complexity: O(log n)"""assert 0 <= l <= self._nassert g(self.e)if l == self._n:return self._nl += self._sizefor i in range(self._log, 0, -1):self._push(l >> i)sm = self.ewhile True:while not l & 1:l >>= 1if not g(self.op(sm, self.tree[l])):while l < self._size:l *= 2if g(self.op(sm, self.tree[l])):sm = self.op(sm, self.tree[l])l += 1return l - self._sizesm = self.op(sm, self.tree[l])l += 1if (l & -l) == l:breakreturn self._ndef min_left(self, r: int, g: Callable[[S], bool]) -> int:"""Return an index l satisfying both:1. l = r or f(op(a[l], a[l + 1], ..., a[r - 1])) = true2. l = 0 or f(op(a[l - 1], a[l + 1], ..., a[r - 1])) = false.If f is monotone, this is the minimum l satisfying:f(op(a[l], a[l + 1], ..., a[r - 1])) = true.Complexity: O(log n)"""assert 0 <= r <= self._nassert g(self.e)if not r:return 0r += self._sizefor i in range(self._log, 0, -1):self._push((r - 1) >> i)sm = self.ewhile True:r -= 1while r > 1 and r & 1:r >>= 1if not g(self.op(self.tree[r], sm)):while r < self._size:r = 2 * r + 1if g(self.op(self.tree[r], sm)):sm = self.op(self.tree[r], sm)r -= 1return r + 1 - self._sizesm = self.op(self.tree[r], sm)if (r & -r) == r:breakreturn 0def nibutan(self, l: int, r: int, g: Callable[[S], bool]) -> int:if self.prod(l, r) > 0:return -1return self.min_left(r, g)class HeavyLightDecomposition(object):def __init__(self, G, root=0):N = len(G)self._par = [-1] * Nself._size = [1] * Nself._heavy_child = [-1] * Nself._head = [0] * Nself._order = [0] * Nself._dfs_heavy_child(G, root)self._dfs_decomposition(G, root)def _dfs_heavy_child(self, G, root):par, size, heavy_child = self._par, self._size, self._heavy_childstack = [~root, root]while stack:v = stack.pop()if v >= 0:for nv in G[v]:if nv != par[v]:par[nv] = vstack.append(~nv)stack.append(nv)else:v = ~vif par[v] != -1:size[par[v]] += size[v]for nv in G[v]:if nv == par[v]:continueif heavy_child[v] == -1 or size[nv] > size[heavy_child[v]]:heavy_child[v] = nvdef _dfs_decomposition(self, G, root):par, size, heavy_child = self._par, self._size, self._heavy_childhead, order = self._head, self._orderstack = [root]count = 0while stack:v = stack.pop()order[v] = countcount += 1if order[par[v]] == order[v] - 1:head[v] = head[par[v]]else:head[v] = vfor nv in G[v]:if nv != par[v] and nv != heavy_child[v]:stack.append(nv)if heavy_child[v] != -1:stack.append(heavy_child[v])def lca(self, u, v):par, head, order = self._par, self._head, self._orderwhile True:if order[u] > order[v]:u, v = v, uif head[u] == head[v]:return uv = par[head[v]]def _ascend(self, u, v):par, head, order = self._par, self._head, self._orderres = []while head[u] != head[v]:res.append((order[u], order[head[u]]))u = par[head[u]]if u != v:res.append((order[u], order[v] + 1))return resdef _descend(self, u, v):return [(j, i) for i, j in self._ascend(v, u)[::-1]]def path(self, u, v, edge=False):l = self.lca(u, v)return self._ascend(u, l) + ([] if edge else [(self._order[l], self._order[l])]) + self._descend(l, v)def get_order(self):return self._orderdef edge_to_order(self, E):par, order = self._par, self._orderreturn [order[u] if par[u] == v else order[v] for u, v in E]class DualSegmentTree:def __init__(self, size, f, default):self.n = (size-1).bit_length()self.size = 1<<self.nself.default = defaultself.lazy = [default]*(self.size*2)self.f = fdef propagate(self, k):lazy = self.lazyif lazy[k] != self.default:lazy[2*k] = self.f(lazy[2*k], lazy[k])lazy[2*k+1] = self.f(lazy[2*k+1], lazy[k])lazy[k] = self.defaultdef thrust(self, k):for i in range(self.n,0,-1):self.propagate(k>>i)def update(self, a, b, x):a += self.sizeb += self.size-1self.thrust(a)self.thrust(b)l = ar = b + 1lazy = self.lazywhile l < r:if l & 1:lazy[l] = self.f(lazy[l], x)l += 1if r & 1:r -= 1lazy[r] = self.f(lazy[r], x)l >>= 1r >>= 1def get(self, k):k += self.sizeself.thrust(k)return self.lazy[k]N, Q = map(int, input().split())_A = [10**18] * NG = [[] for _ in range(N)]E = []for _ in range(N - 1):u, v, w = map(int, input().split())u-=1v-=1G[u].append(v)G[v].append(u)E.append((u, v, w))hld = HeavyLightDecomposition(G)for u,v,w in E:#print(u,v,hld._par[u])if hld._par[u] == v:_A[u] = welse:_A[v] = worder = hld.get_order()A = [0] * Nt = 0for i, a in zip(order, _A):A[i] = a# (a dot b)(x) = b(a(x))# bh(ahx + al) + bl = ahbhx + albh + bldef dot1(a, b):ah, al = divmod(a, MOD)bh, bl = divmod(b, MOD)return (ah * bh % MOD) * MOD + (al * bh + bl) % MODdot2 = lambda a, b: dot1(b, a)##############################e = 10**18id_ = 0def op(s, t):return min(s, t)def mapping(f, a):return a + fdef composition(f, g):return f + g##############################tree1 = LazySegmentTree(A, e, op, id_, mapping, composition)tree2 = DualSegmentTree(N, lambda x, y: x + y, 0)for i in range(N):j = order[i]tree2.update(j, j+1, hld._size[i])for _ in range(Q):t, *aa = map(int, input().split())if t == 1:v, x = aav -= 1y = (10**18, 10**9)pt = hld.path(0, v)for i, j in pt[::-1]:if i <= j:tree1.apply_range(i, j+1, -x)else:tree1.apply_range(j, i+1, -x)w = -2for i, j in pt[::-1]:if i <= j:v = tree1.nibutan(i, j+1, lambda x:x > 0)else:v = tree1.nibutan(j, i+1, lambda x:x > 0)if v != -2:w = v-1breakif w == -2:continuez = tree2.get(w)for i, j in pt:if i <= j:tree2.update(i, j+1, -z)else:tree2.update(j, i+1, -z)c = 10**18for i, j in hld.path(0, w):if i <= j:c = min(c, tree1.prod(i, j+1))else:c = min(c, tree1.prod(j, i+1))b = A[w] - cfor i, j in hld.path(0, w):if i <= j:v = tree1.apply_range(i, j+1, b)else:v = tree1.apply_range(j, i+1, b)elif t == 2:print(tree2.get(0))