abc 187 E - Through Path
"「ある頂点の子孫でない頂点に xを足す」は、
「根の子孫に xを足す」と「ある頂点の子孫に -xを足す」に分けることができるので、
全てのクエリを「ある頂点の子孫に x を足す」の形に帰着することができます。"
かしこい。は?となりながら解説の言うとおりにやってみたら確かにできた。
2つ条件があって、一つが簡単に書けるときは、もう一方をその条件に帰着できないか考えるのが大事なのかなと思った。あと木の上で総和を求めていくのも初だった。
import sys input = sys.stdin.readline from collections import deque n = int(input()) h = [0]*n g = [[] * n for i in range(n)] for i in range(n-1): u, v = map(int, input().split()) u -= 1 v -= 1 g[u].append(v) g[v].append(u) h[i] = (u,v) que = deque() que.append((0,1)) dep = [0]*n chk = [False]*n chk[0] = True cnt = 1 while que: now,p = que.popleft() if cnt == n: break for i in g[now]: if not chk[i]: dep[i] = p chk[i] = True cnt += 1 que.append((i,p+1)) ans = [0]*n q = int(input()) for i in range(q): t,e,x = map(int, input().split()) e -= 1 a,b = h[e] if t == 2: a,b = b,a if dep[a] < dep[b]: ans[b] -= x ans[0] += x else: ans[a] += x que = deque() que.append(0) chk = [False]*n chk[0] = True cnt = 1 while que: now = que.popleft() if cnt == n: break for i in g[now]: if not chk[i]: ans[i] += ans[now] chk[i] = True cnt += 1 que.append(i) print(*ans,sep='\n')