#pragma GCC optimize ("O3") #pragma GCC target ("avx") #include using namespace std; #define getchar getchar_unlocked #define putchar putchar_unlocked int in() { int n, c; while ((c = getchar()) < '0') if (c == EOF) return -1; n = c - '0'; while ((c = getchar()) >= '0') n = n * 10 + c - '0'; return n; } void putInt(int n) { int res[11], i = 0; do { res[i++] = n % 10, n /= 10; } while (n); while (i) putchar(res[--i] + '0'); putchar('\n'); } const int mod = 1e9 + 7; int add(int a, int b) { return (a += b) >= mod ? a - mod : a; } int sub(int a, int b) { return add(a, mod - b); } int mul(int a, int b) { return 1LL * a * b % mod; } const int N = 2e5 + 10; struct Node { int64_t sum0 = 0; int64_t sum1 = 0; }; Node nodes[N]; int w[N + 1]; int64_t ss[N + 1]; int offset; int size; void addPoint(int k, int64_t v0, int64_t v1) { Node *ft = nodes + offset; v0 %= mod; v1 %= mod; k -= offset; k++; while (k <= size) { ft[k].sum0 += v0; ft[k].sum1 += v1; k += k & -k; } } int64_t sum(int k) { Node *ft = nodes + offset; k++; int x = k; k -= offset; int64_t res0 = 0; int64_t res1 = 0; while (k > 0) { res0 += ft[k].sum0; res1 += ft[k].sum1; k &= k - 1; } res1 %= mod; return (res0 + res1 * sub(w[x], w[offset])) % mod; } int sum(int l, int r) { return sub(sum(r - 1), sum(l - 1)); } void add(int l, int r, int value) { addPoint(l, 1LL * (mod - value) * sub(w[l], w[offset]), value); addPoint(r, 1LL * value * sub(w[r], w[offset]), mod - value); } class HeavyLightDecomposition { private: const vector> &g; public: struct Node { int vid; int head; int parent; int heavy; int length; }; vector nodes; HeavyLightDecomposition(const vector> &g) : g(g), nodes(g.size()) { dfs(0, -1); bfs(0); } void forEach(int u, int v, function f) { while (true) { if (nodes[u].vid > nodes[v].vid) { swap(u, v); } int h = nodes[v].head; int l = nodes[h].length; if (nodes[u].head == nodes[v].head) { f(nodes[h].vid, l, nodes[u].vid, nodes[v].vid); break; } else { f(nodes[h].vid, l, nodes[h].vid, nodes[v].vid); v = nodes[h].parent; } } } int operator[](int k) { return nodes[k].vid; } private: int dfs(int curr, int prev) { nodes[curr].heavy = -1; nodes[curr].parent = prev; int maxSub = 0; int sub = 1; for (int next : g[curr]) { if (next == prev) { continue; } int subNext = dfs(next, curr); sub += subNext; if (maxSub < subNext) { maxSub = subNext; nodes[curr].heavy = next; } } return sub; } void bfs(int s) { queue q; q.push(s); int k = 0; while (!q.empty()) { int h = q.front(); q.pop(); for (int i = h; i != -1; i = nodes[i].heavy) { nodes[i].vid = k++; nodes[i].head = h; nodes[h].length++; for (int j : g[i]) { if (j != nodes[i].parent && j != nodes[i].heavy) { q.push(j); } } } } } }; int main() { int n; cin >> n; vector s(n); vector c(n); for (int i = 0; i < n; i++) { s[i] = in(); } for (int i = 0; i < n; i++) { c[i] = in(); } vector> g(n); for (int i = 0; i < n - 1; i++) { int a = in() - 1; int b = in() - 1; g[a].push_back(b); g[b].push_back(a); } HeavyLightDecomposition hld(g); for (int i = 0; i < n; i++) { ss[hld[i] + 1] = s[i]; w[hld[i] + 1] = c[i]; } for (int i = 1; i < N; i++) { ss[i] += ss[i - 1]; w[i] = add(w[i], w[i - 1]); } int q; cin >> q; for (int i = 0; i < q; i++) { int t; t = in(); if (t == 0) { int u = in() - 1; int v = in() - 1; int z = in(); hld.forEach(u, v, [&](int head, int len, int l, int r) { offset = head; size = len; add(l, r + 1, z); }); } else { int u = in() - 1; int v = in() - 1; int64_t ans = 0; hld.forEach(u, v, [&](int head, int len, int l, int r) { offset = head; size = len; ans += sum(l, r + 1); ans += ss[r + 1] - ss[l]; }); putInt(ans % mod); } } }