#ifdef ONLINE_JUDGE #pragma GCC target("avx2,avx") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") #endif #include using namespace std; using ll = long long; using ull = unsigned long long; using i128 = __int128_t; using pii = pair; using pll = pair; #define rep(i, n) for (int i = 0; i < (n); i++) #define all(x) (x).begin(), (x).end() constexpr char ln = '\n'; istream& operator>>(istream& is, __int128_t& x) { x = 0; string s; is >> s; int n = int(s.size()), it = 0; if (s[0] == '-') it++; for (; it < n; it++) x = (x * 10 + s[it] - '0'); if (s[0] == '-') x = -x; return is; } ostream& operator<<(ostream& os, __int128_t x) { if (x == 0) return os << 0; if (x < 0) os << '-', x = -x; deque deq; while (x) deq.emplace_front(x % 10), x /= 10; for (int e : deq) os << e; return os; } template ostream& operator<<(ostream& os, const pair& p) { return os << "(" << p.first << ", " << p.second << ")"; } template ostream& operator<<(ostream& os, const vector& v) { os << "{"; for (int i = 0; i < int(v.size()); i++) { if (i) os << ", "; os << v[i]; } return os << "}"; } template inline int SZ(Container& v) { return int(v.size()); } template inline void UNIQUE(vector& v) { v.erase(unique(v.begin(), v.end()), v.end()); } template inline bool chmax(T1& a, T2 b) { if (a < b) {a = b; return true ;} return false ;} template inline bool chmin(T1& a, T2 b) { if (a > b) {a = b; return true ;} return false ;} inline int topbit(int x) { return x == 0 ? -1 : 31 - __builtin_clz(x); } inline int topbit(long long x) { return x == 0 ? -1 : 63 - __builtin_clzll(x); } inline int botbit(int x) { return x == 0 ? 32 : __builtin_ctz(x); } inline int botbit(long long x) { return x == 0 ? 64 : __builtin_ctzll(x); } inline int popcount(int x) { return __builtin_popcount(x); } inline int popcount(long long x) { return __builtin_popcountll(x); } inline int kthbit(long long x, int k) { return (x>>k) & 1; } inline constexpr long long TEN(int x) { return x == 0 ? 1 : TEN(x-1) * 10; } namespace detail { template auto make_vector(vector& sizes, Tp const& x) { if constexpr (Nb == 1) { return vector(sizes[0], x); } else { int size = sizes[Nb-1]; sizes.pop_back(); return vector(size, make_vector(sizes, x)); } } } template auto make_vector(int const(&sizes)[Nb], Tp const& x = Tp()) { vector s(Nb); for (int i = 0; i < Nb; i++) s[i] = sizes[Nb-i-1]; return detail::make_vector(s, x); } inline void print() { cout << "\n"; } template inline void print(const vector& v) { for (int i = 0; i < int(v.size()); i++) { if (i) cout << " "; cout << v[i]; } print(); } template inline void print(const T& x, const Args& ... args) { cout << x << " "; print(args...); } #ifdef MINATO_LOCAL inline void debug_out() { cerr << endl; } template inline void debug_out(const T& x, const Args& ... args) { cerr << " " << x; debug_out(args...); } #define debug(...) cerr << __LINE__ << " : [" << #__VA_ARGS__ << "] =", debug_out(__VA_ARGS__) #define dump(x) cerr << __LINE__ << " : " << #x << " = " << (x) << endl; #else #define debug(...) (void(0)) #define dump(x) (void(0)) #endif struct fast_ios { fast_ios() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(20); }; } fast_ios_; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// struct HeavyLightDecomposition { vector> G; vector vid, head, sub, par, dep, inv, type; HeavyLightDecomposition(int N) : G(N),vid(N,-1),head(N),sub(N,1), par(N,-1),dep(N,0),inv(N),type(N){} void add_edge(int u,int v) { G[u].emplace_back(v); G[v].emplace_back(u); } void build(vector rs = {0}) { int c = 0, pos = 0; for(int r : rs) { dfs_sz(r); head[r] = r; dfs_hld(r, c++, pos); } } void dfs_sz(int v) { for(int& u : G[v]) if(u==par[v]) swap(u,G[v].back()); if(~par[v]) G[v].pop_back(); for (int& u : G[v]) { par[u] = v; dep[u] = dep[v]+1; dfs_sz(u); sub[v] += sub[u]; if(sub[u] > sub[G[v][0]]) swap(u,G[v][0]); } } void dfs_hld(int v, int c, int& pos) { vid[v] = pos++; inv[vid[v]] = v; type[v] = c; for(int u : G[v]) { if(u == par[v]) continue; head[u] = (u == G[v][0] ? head[v] : u); dfs_hld(u,c,pos); } } int lca(int u, int v) { while(true) { if(vid[u] > vid[v]) swap(u,v); if(head[u] == head[v]) return u; v = par[head[v]]; } } int distance(int u, int v) { return dep[u] + dep[v] - 2*dep[lca(u,v)]; } // for_each(vertex) template void for_each(int u, int v, const F& f) { while(true) { if(vid[u] > vid[v]) swap(u,v); f(max(vid[head[v]],vid[u]), vid[v]+1); if(head[u] != head[v]) v = par[head[v]]; else break; } } template T for_each(int u, int v, T ti, const Q& q, const F& f) { T l = ti, r = ti; while(true) { if(vid[u] > vid[v]) { swap(u,v); swap(l,r); } l = f(l, q(max(vid[head[v]],vid[u]), vid[v]+1)); if(head[u] != head[v]) v = par[head[v]]; else break; } return f(l,r); } // for_each(edge) // [l, r) <- attention!! template void for_each_edge(int u, int v, const F& f) { while(true) { if (vid[u] > vid[v]) swap(u,v); if (head[u] != head[v]) { f(vid[head[v]],vid[v]+1); v = par[head[v]]; } else { if (u != v) f(vid[u]+1, vid[v]+1); break; } } } int search(int v, int d) { if (dep[v] < d || d < 0) return -1; while (true) { if (dep[v] - dep[head[v]] + 1 <= d) { d -= dep[v] - dep[head[v]] + 1; v = par[head[v]]; } else { return inv[vid[v]-d]; } } } }; template struct LazySegmentTree { private: F op; G mapping; H composition; T e; U id; int _n, size ,log; vector node; vector lazy; public: LazySegmentTree() {} LazySegmentTree(const F& op, const G& mapping, const H& composition, T e, U id, int n) : LazySegmentTree(op, mapping, composition, e, id, vector(n, e)) {} LazySegmentTree(const F& op, const G& mapping, const H& composition, T e, U id, const vector& v) : op(op), mapping(mapping), composition(composition), e(e), id(id), _n(int(v.size())), log(0) { while ((1<(2 * size, e); lazy = vector(size, id); for (int i = 0; i < _n; i++) node[size + i] = v[i]; for (int i = size - 1; i >= 1; i--) { update(i); } } void set(int p, T x) { assert(0 <= p && p < _n); p += size; for (int i = log; i >= 1; i--) push(p >> i); node[p] = x; for (int i = 1; i <= log; i++) update(p >> i); } // [l, r) (0-indexed) T get(int l, int r) { if (l >= r) return e; l += size; r += size; for (int i = log; i >= 1; i--) { if (((l >> i) << i) != l) push(l >> i); if (((r >> i) << i) != r) push(r >> i); } T sml = e, smr = e; while (l < r) { if (l & 1) sml = op(sml, node[l++]); if (r & 1) smr = op(node[--r], smr); l >>= 1; r >>= 1; } return op(sml, smr); } T all_get() { return node[1]; } void apply(int p, U val) { assert(0 <= p && p < _n); p += size; for (int i = log; i >= 1; i--) push(p >> i); node[p] = val == id ? node[p] : mapping(node[p], val); for (int i = 1; i <= log; i++) update(p >> i); } void apply(int l, int r, U val) { if (l >= r) return; l += size; r += size; for (int i = log; i >= 1; i--) { if (((l >> i) << i) != l) push(l >> i); if (((r >> i) << i) != r) push((r - 1) >> i); } { int l2 = l, r2 = r; while (l < r) { if (l & 1) all_apply(l++, val); if (r & 1) all_apply(--r, val); l >>= 1; r >>= 1; } l = l2; r = r2; } for (int i = 1; i <= log; i++) { if (((l >> i) << i) != l) update(l >> i); if (((r >> i) << i) != r) update((r - 1) >> i); } } template int max_right(int l, const C& check) { assert(0 <= l && l <= _n); assert(check(e)); if (l == _n) return _n; l += size; for (int i = log; i >= 1; i--) push(l >> i); T sm = e; do { while (~l & 1) l >>= 1; if (!check(op(sm, node[l]))) { while (l < size) { push(l); l = (2 * l); if (check(op(sm, node[l]))) { sm = op(sm, node[l]); l++; } } return l - size; } sm = op(sm, node[l]); l++; } while ((l & -l) != l); return _n; } template int min_left(int r, const C& check) { assert(0 <= r && r <= _n); assert(check(e)); if (r == 0) return 0; r += size; for (int i = log; i >= 1; i--) push((r - 1) >> i); T sm = e; do { r--; while (r > 1 && (r & 1)) r >>= 1; if (!check(op(node[r], sm))) { while (r < size) { push(r); r = (2 * r + 1); if (check(op(node[r], sm))) { sm = op(node[r], sm); r--; } } return r + 1 - size; } sm = op(node[r], sm); } while ((r & -r) != r); return 0; } T operator[](int p) { assert(0 <= p && p < _n); p += size; for (int i = log; i >= 1; i--) push(p >> i); return node[p]; } private: void update(int k) { node[k] = op(node[2 * k], node[2 * k + 1]); } void all_apply(int k, U val) { node[k] = val == id ? node[k] : mapping(node[k], val); if (k < size) lazy[k] = composition(lazy[k], val); } void push(int k) { if (lazy[k] == id) return; all_apply(2 * k, lazy[k]); all_apply(2 * k + 1, lazy[k]); lazy[k] = id; } }; template struct edge { int src,to; T cost; int id; edge(){} edge(int to, T cost) : src(-1), to(to), cost(cost), id(-1) {} edge(int src, int to, T cost) : src(src), to(to), cost(cost), id(-1) {} edge(int src, int to, T cost, int id) : src(src), to(to), cost(cost), id(id) {} bool operator<(const edge& e) const { return cost < e.cost; } }; int main() { int N; cin >> N; vector> E(N-1); HeavyLightDecomposition HLD(N); rep(i,N-1) { int u,v,w; cin >> u >> v >> w; E[i] = edge(u,v,w); HLD.add_edge(u,v); } HLD.build(); auto f=[](pll a, pll b) { return pll(a.first+b.first,a.second+b.second); }; auto g=[](pll a, ll val) { return pll(a.first+val*a.second,a.second); }; auto h=[](ll a, ll b) { return a+b; }; constexpr pll e = pll(0,0); constexpr ll id = 0; LazySegmentTree seg(f,g,h,e,id,N); rep(i,N-1) { int u = E[i].src; int v = E[i].to; if (HLD.dep[u] < HLD.dep[v]) { seg.set(HLD.vid[v],pll(E[i].cost,1)); } else { seg.set(HLD.vid[u],pll(E[i].cost,-1)); } } int Q; cin >> Q; rep(_,Q) { int t; cin >> t; if (t==1) { int a,x; cin >> a >> x; seg.apply(HLD.vid[a]+1,HLD.vid[a]+HLD.sub[a],x); } else { int b; cin >> b; ll ans = 0; auto func=[&](int a, int b) { ans += seg.get(a,b).first; return; }; HLD.for_each_edge(0,b,func); cout << ans << ln; } } }