#include "bits/stdc++.h" using namespace std; #define FOR(i,j,k) for(int (i)=(j);(i)<(int)(k);++(i)) #define rep(i,j) FOR(i,0,j) #define each(x,y) for(auto &(x):(y)) #define mp make_pair #define all(x) (x).begin(),(x).end() #define debug(x) cout<<#x<<": "<<(x)< pii; typedef vector vi; typedef vector vll; template class ModInt{ public: ModInt():value(0){} ModInt(long long val):value((int)(val<0?MOD+val%MOD:val%MOD)){ } ModInt& operator+=(ModInt that){ value = value+that.value; if(value>=MOD)value-=MOD; return *this; } ModInt& operator-=(ModInt that){ value -= that.value; if(value<0)value+=MOD; return *this; } ModInt& operator*=(ModInt that){ value = (int)((long long)value * that.value % MOD); return *this; } ModInt &operator/=(ModInt that){ return *this *= that.inverse(); } ModInt operator+(ModInt that) const{ return ModInt(*this)+=that; } ModInt operator-(ModInt that) const{ return ModInt(*this)-=that; } ModInt operator*(ModInt that) const{ return ModInt(*this)*=that; } ModInt operator/(ModInt that) const { return ModInt(*this) /= that; } ModInt operator^(long long k) const{ if(value == 0)return 0; ModInt n = *this, res = 1; while(k){ if(k & 1)res *= n; n *= n; k >>= 1; } return res; } ModInt inverse() const { long long a = value, b = MOD, u = 1, v = 0; while(b) { long long t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v); } return ModInt(u); } int toi() const{ return value; } private: int value; }; typedef ModInt<1000000007> mint; ostream& operator<<(ostream& os, const mint& x){ os << x.toi(); return os; } struct HLDecomposition{ vector parent, depth, sub, id, head; int cur = 0; HLDecomposition(const vector > &G){ parent = depth = sub = id = head = vector(G.size()); dfs(G, 0, -1, 0); dfs2(G, 0, -1, 0); } int dfs(const vector > &G, int u, int pre, int d){ parent[u] = pre; sub[u] = 1; depth[u] = d; for(int v: G[u]) if(v != pre) sub[u] += dfs(G, v, u, d+1); return sub[u]; } void dfs2(const vector >&G, int u, int pre, int h){ head[u] = h; id[u] = cur++; int heavy = -1, maxi = 0; for(int v : G[u]){ if(v != pre && maxi < sub[v]){ maxi = sub[v]; heavy = v; } } if(heavy != -1)dfs2(G, heavy, u, h); for(int v : G[u]){ if(v != pre&&v != heavy){ dfs2(G, v, u, v); } } } vector > goUpToLCA(int u, int v){ vector > res; while(true){ if(head[u]==head[v]){ if(depth[u] > depth[v])swap(u, v); res.emplace_back(id[u], id[v] + 1); break; } else{ if(depth[head[u]] > depth[head[v]])swap(u, v); res.emplace_back(id[head[v]], id[v] + 1); v = parent[head[v]]; } } return res; } }; vector sumC; bool init = true; struct LazySegTreeSum{ int dataSize; vector value, lazy; LazySegTreeSum(int n){ dataSize = 1; while(dataSize < n)dataSize *= 2; int treeSize = 2 * dataSize; value = lazy = vector(treeSize); } void propagate(int index, int curL, int curR){ // 自分の値をlazyにもとづいて書き換えて自分のlazyをクリア。 if(lazy[index].toi()){ int left = index * 2 + 1, right = index * 2 + 2; if(!init)value[index] += lazy[index] * (sumC[curR]-sumC[curL]); else value[index] += lazy[index] * (curR - curL); // 子のlazyを書き換える。 if(curR - curL > 1){ lazy[left] += lazy[index]; lazy[right] += lazy[index]; } lazy[index] = 0; } } // [curL, curR) を評価する void update(int index, int curL, int curR, int givenL, int givenR, int x){ // 範囲外であろうとpropagateは必ず呼ぶ。そうでないと、親がうまく評価されない propagate(index, curL, curR); // 範囲外 if(curR <= givenL || givenR <= curL)return; if(givenL <= curL && curR <= givenR){ // 直接書き換えないでindexのlazyを書き換えてpropagateを呼ぶ lazy[index] += x; propagate(index, curL, curR); } else{ int mid = (curL + curR) / 2; update(index * 2 + 1, curL, mid, givenL, givenR, x); update(index * 2 + 2, mid, curR, givenL, givenR, x); value[index] = value[index * 2 + 1] + value[index * 2 + 2]; } } void update(int l, int r, int x){ update(0, 0, dataSize, l, r, x); } mint query(int l, int r){ return query(0, 0, dataSize, l, r); } mint query(int index, int curL, int curR, int givenL, int givenR){ // 範囲外 if(curR <= givenL || givenR <= curL)return 0; propagate(index, curL, curR); if(givenL <= curL && curR <= givenR){ return value[index]; } else{ int mid = (curL + curR) / 2; mint resL = query(index * 2 + 1, curL, mid, givenL, givenR); mint resR = query(index * 2 + 2, mid, curR, givenL, givenR); return resL + resR; } } }; int main(){ int N; cin >> N; vi S(N), C(N); rep(i, N)scanf("%d", &S[i]); rep(i, N)scanf("%d", &C[i]); vector G(N); rep(i, N-1){ int a, b; scanf("%d%d", &a, &b); --a; --b; G[a].push_back(b); G[b].push_back(a); } auto hlc = HLDecomposition(G); LazySegTreeSum st(N); int M = st.dataSize; sumC = vector(M+1); rep(i, N){ int u = hlc.id[i]; st.update(u, u + 1, S[i]); sumC[u+1] = C[i]; } rep(i, M)sumC[i + 1] += sumC[i]; init = false; int Q; cin >> Q; while(Q--){ int q, x, y; scanf("%d%d%d", &q, &x, &y); --x; --y; if(q == 0){ int z; scanf("%d", &z); auto segs = hlc.goUpToLCA(x, y); each(seg, segs){ st.update(seg.first, seg.second, z); } } else{ mint ans; auto segs = hlc.goUpToLCA(x, y); each(seg, segs){ ans += st.query(seg.first, seg.second); } printf("%d\n", ans.toi()); } } }