#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using int32 = std::int_fast32_t; using int64 = std::int_fast64_t; using uint32 = std::uint_fast32_t; using uint64 = std::uint_fast64_t; using intl32 = std::int_least32_t; using intl64 = std::int_least64_t; using uintl32 = std::uint_least32_t; using uintl64 = std::uint_least64_t; template class link_cut_tree { struct node_t { node_t *left, *right, *per; Semigroup value, sum; Operand lazy; std::uint_least8_t b; // isnotroot reverse haslazy node_t() :left(nullptr), right(nullptr), per(nullptr), value(Semigroup()) , sum(Semigroup()), b(0) {} Semigroup reflect() { if (b & 1) { if (b & 2) return ~(sum*lazy); return sum*lazy; } if (b & 2) return ~sum; return sum; } void assign(Operand &data) { if (b & 1) lazy = lazy*data; else { lazy = data;b |= 1; } } void push() { if (b & 2) { std::swap(left, right); if (left) left->b ^= 2; if (right)right->b ^= 2; value = ~value; } if (b & 1) { value = value*lazy; if (left)left->assign(lazy); if (right) right->assign(lazy); } b &= ~3; } void propagate() { if (per) per->propagate(); push(); } void splay() { node_t *x = this, *pp; while (x->b & 4) { if (!(per->b & 4)) { if (per->left == this) { per->left = right; per->recalc(); right = per; } else { per->right = left; per->recalc(); left = per; } x = per; per = per->per; recalc(); break; } x = per->per; pp = x->per; if (per->left == this) { if (x->left == per) { x->left = per->right; per->left = right; per->right = x; right = per; } else { x->right = left; per->left = right; right = per; left = x; } } else { if (x->right == per) { x->right = per->left; per->right = left; per->left = x; left = per; } else { x->left = right; per->right = left; left = per; right = x; } } x->recalc(); per->recalc(); recalc(); per = pp; if (pp) { if (pp->left == x) { pp->left = this; } else { pp->right = this; } } } x->b |= 4; } void expose(node_t *prev) { splay(); if (right)right->b &= ~4; right = prev; recalc(); if (per)per->expose(this); else b &= ~4; } void recalc() { sum = value; if (left) { sum = left->reflect() + sum; left->per = this; } if (right) { sum = sum + right->reflect(); right->per = this; } } }; std::vector tree; void expose(node_t *n) { n->propagate(); n->expose(nullptr); n->splay(); n->b &= ~4; n->recalc(); } //* struct vis { int32 l, r, p, rev; }; std::vector v; //*/ public: link_cut_tree(uint32 size) :tree(size) {} link_cut_tree(std::vector &a) :tree(a.size()) { for (uint32 i = 0;i < a.size();++i) { tree[i].value = tree[i].sum = a[i]; } } void link(uint32 child, uint32 per) { evert(child); tree[child].per = &tree[per]; } void cut(uint32 child) { node_t *n = &tree[child]; expose(n); if (n->left) { n->left->per = nullptr; n->left->b &= ~4; n->left = nullptr; } n->sum = n->value; } void update(uint32 u, uint32 v, const Operand &data) { evert(u); expose(&tree[v]); tree[v].lazy = data; tree[v].b |= 1; } Semigroup path(uint32 u, uint32 v) { evert(u); expose(&tree[v]); return tree[v].sum; } void evert(uint32 v) { expose(&tree[v]); tree[v].b ^= 2; } //* int32 ch(node_t *n) { if (!n) return -9; return n - &tree[0]; } void scan(void) { v = std::vector(tree.size()); for (uint32 i = 0;i < tree.size();++i) { v[i] = { ch(tree[i].left),ch(tree[i].right),ch(tree[i].per),tree[i].b & 2 }; } } //*/ }; static constexpr uint64 MOD = 1000000007; struct p { uint64 data; p(){} p(uint64 x) :data(x) {} p operator*(const p &other) { return p((data + other.data) % MOD); } }; struct meguru { uint64 s, c; meguru(){} meguru(uint64 x,uint64 y):s(x),c(y){} meguru operator~() { return *this; } meguru operator+(const meguru &other) { return meguru((s + other.s)%MOD, (c + other.c)%MOD); } meguru operator*(const p &other) { return meguru((s + c*other.data) % MOD, c); } }; int main(void) { std::ios::sync_with_stdio(false); std::cin.tie(0); uint32 n; std::cin >> n; std::vector D(n); uint64 s, c; for (uint32 i = 0;i < n;++i) { std::cin >> s; D[i].s = s; } for (uint32 i = 0;i < n;++i) { std::cin >> c; D[i].c = c; } link_cut_tree L(D); uint32 a, b; for (uint32 i = 1;i < n;++i) { std::cin >> a >> b; L.link(a - 1, b - 1); //L.scan(); } uint32 q; std::cin >> q; uint64 que, x, y, z; while (q--) { //L.scan(); std::cin >> que >> x >> y; if (que) { std::cout << L.path(x - 1, y - 1).s << "\n"; } else { std::cin >> z; L.update(x - 1, y - 1, p(z)); } } return 0; }