#include #define GET_MACRO(a, b, c, NAME, ...) NAME #define rep(...) GET_MACRO(__VA_ARGS__, rep3, rep2)(__VA_ARGS__) #define rep2(i, a) rep3 (i, 0, a) #define rep3(i, a, b) for (int i = (a); i < (b); i++) #define repr(...) GET_MACRO(__VA_ARGS__, repr3, repr2)(__VA_ARGS__) #define repr2(i, a) repr3 (i, 0, a) #define repr3(i, a, b) for (int i = (b) - 1; i >= (a); i--) #define chmin(a, b) ((b) < a && (a = (b), true)) #define chmax(a, b) (a < (b) && (a = (b), true)) using namespace std; typedef long long ll; const ll mod = 1e9 + 7; ll modulo(ll a) { a %= mod; a += mod; a %= mod; return a; } struct HL { vector> g; vector heavy, vid, depth, head, parent, size; int u, v, l, r; HL(int n) : g(n), heavy(n, n), vid(n, -1), depth(n), head(n), parent(n), size(n + 1, 1) {} void add(int u, int v) { g[u].push_back(v); g[v].push_back(u); } void build() { int k = 0; dfs(0, -1); dfs2(0, -1, k); } void dfs(int curr, int prev) { head[curr] = curr; parent[curr] = prev; for (int next : g[curr]) if (next != prev) { depth[next] = depth[curr] + 1; dfs(next, curr); size[curr] += size[next]; if (size[heavy[curr]] <= size[heavy[next]]) heavy[curr] = next; } } void dfs2(int curr, int prev, int &k) { vid[curr] = k++; if (heavy[curr] < g.size()) { int next = heavy[curr]; head[next] = head[curr]; dfs2(next, curr, k); } for (int next : g[curr]) if (next != prev && next != heavy[curr]) { dfs2(next, curr, k); } } void set(int u, int v) { this->u = u, this->v = v; } void next() { if (depth[head[u]] < depth[head[v]]) swap(u, v); if (head[u] == head[v]) { tie(l, r) = minmax(vid[u], vid[v]); u = -1; } else { l = vid[head[u]]; r = vid[u]; u = parent[head[u]]; } r++; } bool has_next() { return u != -1; } }; struct SegmentTree { vector seg, lazy, weight, wsum; int size; SegmentTree(int n) { size = 1; while (size < n) size *= 2; seg.resize(size * 2); lazy.resize(size * 2); weight.resize(size); } void set(int k, ll v, ll w) { seg[k + size - 1] = v; weight[k] = w; } void build() { wsum.resize(size + 1); rep (i, size) { wsum[i + 1] += wsum[i] + weight[i]; wsum[i + 1] %= mod; } repr (i, size - 1) { seg[i] = seg[i * 2 + 1] + seg[i * 2 + 2]; seg[i] %= mod; } } void push(int k, int l, int r) { if (lazy[k] != 0) { seg[k] += lazy[k] * (wsum[r] - wsum[l]); seg[k] = modulo(seg[k]); if (r - l > 1) { (lazy[k * 2 + 1] += lazy[k]) %= mod; (lazy[k * 2 + 2] += lazy[k]) %= mod; } lazy[k] = 0; } } void update(int a, int b, ll v, int k, int l, int r) { push(k, l, r); if (r <= a || b <= l) return; if (a <= l && r <= b) { lazy[k] = v; push(k, l, r); } else { update(a, b, v, k * 2 + 1, l, (l + r) / 2); update(a, b, v, k * 2 + 2, (l + r) / 2, r); seg[k] = seg[k * 2 + 1] + seg[k * 2 + 2]; seg[k] %= mod; } } void update(int a, int b, ll v) { update(a, b, v, 0, 0, size); } ll query(int a, int b, int k, int l, int r) { push(k, l, r); if (r <= a || b <= l) return 0; if (a <= l && r <= b) return seg[k]; ll res = 0; res += query(a, b, k * 2 + 1, l, (l + r) / 2); res += query(a, b, k * 2 + 2, (l + r) / 2, r); return res % mod; } ll query(int a, int b) { return query(a, b, 0, 0, size); } }; int main() { int N; cin >> N; vector S(N), C(N); rep (i, N) scanf("%d", &S[i]); rep (i, N) scanf("%d", &C[i]); HL hl(N); rep (i, N - 1) { int a, b; cin >> a >> b; hl.add(a - 1, b - 1); } hl.build(); SegmentTree tr(N); rep (i, N) tr.set(hl.vid[i], S[i], C[i]); tr.build(); int Q; cin >> Q; while (Q--) { int q; scanf("%d", &q); if (q == 0) { int x, y, z; scanf("%d%d%d", &x, &y, &z); x--; y--; hl.set(x, y); while (hl.has_next()) { hl.next(); tr.update(hl.l, hl.r, z); } } else { int x, y; scanf("%d%d", &x, &y); x--; y--; hl.set(x, y); ll ans = 0; while (hl.has_next()) { hl.next(); ans += tr.query(hl.l, hl.r); ans %= mod; } printf("%d\n", (int)ans); } } }