#include using namespace std; static const long long MOD = 1e9 + 7; // ===================== Data ===================== struct Data { long long val; // 区間の和 long long coef; // 係数 Data(long long v = 0, long long c = 0) : val(v), coef(c) {} }; Data op(const Data& a, const Data& b) { return Data((a.val + b.val) % MOD, (a.coef + b.coef) % MOD); } using Lazy = long long; Data mapping(Lazy f, const Data& x) { long long v = (x.val + x.coef * f) % MOD; return Data(v, x.coef); } // 遅延合成 Lazy composition(Lazy f, Lazy g) { return (f + g) % MOD; } // ===================== LazySegTree ===================== struct LazySegTree { int n, log, size; vector d; vector lz; LazySegTree(int _n, const vector& v) { n = _n; log = 0; while ((1 << log) < n) log++; size = 1 << log; d.assign(2 * size, Data()); lz.assign(size, 0); for (int i = 0; i < n; i++) d[size + i] = v[i]; for (int i = size - 1; i >= 1; i--) update(i); } void update(int k) { d[k] = op(d[2*k], d[2*k+1]); } void all_apply(int k, Lazy f) { d[k] = mapping(f, d[k]); if (k < size) lz[k] = composition(f, lz[k]); } void push(int k) { all_apply(2*k, lz[k]); all_apply(2*k+1, lz[k]); lz[k] = 0; } // 点更新 void set_val(int p, Data x) { p += size; for (int i = log; i >= 1; i--) push(p >> i); d[p] = x; for (int i = 1; i <= log; i++) update(p >> i); } // 点取得 Data get(int p) { p += size; for (int i = log; i >= 1; i--) push(p >> i); return d[p]; } // 区間 apply void apply(int l, int r, Lazy f) { if (l == r) return; l += size; r += size; // push 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++, f); if (r & 1) all_apply(--r, f); l >>= 1; r >>= 1; } // update 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); } } // 区間取得 Data prod(int l, int r) { if (l == r) return Data(); 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); } Data sml, smr; while (l < r) { if (l & 1) sml = op(sml, d[l++]); if (r & 1) smr = op(d[--r], smr); l >>= 1; r >>= 1; } return op(sml, smr); } }; // ===================== HLD ===================== struct HLD { int n; vector vid, inv, par, depth, sub, head, nex, type; vector> adj; HLD(int n, const vector>& g, int root=0) : n(n), adj(g), vid(n, -1), inv(n), par(n, -1), depth(n), sub(n, 1), head(n), nex(n, -1), type(n) { build(root); } void build(int root) { dfs_sz(root); int cur = 0; dfs_hld(root, cur, root, 0); } void dfs_sz(int v) { for (int& to : adj[v]) { if (to == par[v]) continue; par[to] = v; depth[to] = depth[v] + 1; dfs_sz(to); sub[v] += sub[to]; if (nex[v] == -1 || sub[to] > sub[nex[v]]) nex[v] = to; } } void dfs_hld(int v, int& cur, int h, int t) { head[v] = h; type[v] = t; vid[v] = cur; inv[cur] = v; cur++; if (nex[v] != -1) dfs_hld(nex[v], cur, h, t); for (int to : adj[v]) { if (to == par[v] || to == nex[v]) continue; dfs_hld(to, cur, to, t+1); } } // u-v の頂点区間に [l, r] で callback template void foreach_nodes(int u, int v, F f) { while (true) { if (vid[u] > vid[v]) swap(u, v); f(max(vid[head[v]], vid[u]), vid[v]); if (head[u] != head[v]) v = par[head[v]]; else break; } } }; // ===================== main ===================== int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; vector S(N), C(N); for (auto& x : S) cin >> x; for (auto& x : C) cin >> x; vector> adj(N); for (int i = 0; i < N-1; i++) { int a, b; cin >> a >> b; a--, b--; adj[a].push_back(b); adj[b].push_back(a); } HLD hld(N, adj, 0); // HLD に合わせて並べる vector xs(N); for (int i = 0; i < N; i++) { xs[hld.vid[i]] = Data(S[i], C[i]); } LazySegTree seg(N, xs); int Q; cin >> Q; while (Q--) { int t; cin >> t; if (t == 0) { int x, y; long long z; cin >> x >> y >> z; x--, y--; hld.foreach_nodes(x, y, [&](int l, int r) { seg.apply(l, r+1, z); }); } else { int x, y; cin >> x >> y; x--, y--; long long ans = 0; hld.foreach_nodes(x, y, [&](int l, int r) { ans = (ans + seg.prod(l, r+1).val) % MOD; }); cout << ans << "\n"; } } return 0; }