#include using namespace std; const int MOD = 998244353; const int MAXN = 1e5 + 5; long long tree_a[4 * MAXN], tree_b[4 * MAXN]; int in[MAXN], out[MAXN]; vector adj[MAXN]; long long X[MAXN]; int timer; void push(int node, int l, int r) { if (l == r) return; long long a = tree_a[node]; long long b = tree_b[node]; if (a == 1 && b == 0) return; tree_a[2*node] = (a * tree_a[2*node]) % MOD; tree_b[2*node] = (a * tree_b[2*node] + b) % MOD; tree_a[2*node+1] = (a * tree_a[2*node+1]) % MOD; tree_b[2*node+1] = (a * tree_b[2*node+1] + b) % MOD; tree_a[node] = 1; tree_b[node] = 0; } void update_range(int node, int l, int r, int ul, int ur, long long c, long long d) { if (ur < l || ul > r) return; if (ul <= l && r <= ur) { tree_a[node] = (c * tree_a[node]) % MOD; tree_b[node] = (c * tree_b[node] + d) % MOD; return; } push(node, l, r); int mid = (l + r) / 2; update_range(2*node, l, mid, ul, ur, c, d); update_range(2*node+1, mid+1, r, ul, ur, c, d); } pair query_point(int node, int l, int r, int pos) { if (l == r) { return {tree_a[node], tree_b[node]}; } push(node, l, r); int mid = (l + r) / 2; if (pos <= mid) { return query_point(2*node, l, mid, pos); } else { return query_point(2*node+1, mid+1, r, pos); } } int main() { ios::sync_with_stdio(false); cin.tie(0); int N, Q; cin >> N >> Q; for (int i = 0; i < N-1; i++) { int a, b; cin >> a >> b; adj[a].push_back(b); adj[b].push_back(a); } stack> st; st.push({1, -1, false}); timer = 0; while (!st.empty()) { auto [u, p, visited] = st.top(); st.pop(); if (!visited) { in[u] = ++timer; st.push({u, p, true}); for (auto it = adj[u].rbegin(); it != adj[u].rend(); ++it) { int v = *it; if (v != p) { st.push({v, u, false}); } } } else { out[u] = timer; } } for (int i = 1; i <= N; i++) { cin >> X[i]; } for (int i = 1; i <= 4*N; i++) { tree_a[i] = 1; tree_b[i] = 0; } while (Q--) { int type; cin >> type; if (type == 1) { int V; cin >> V; auto [a, b] = query_point(1, 1, N, in[V]); long long ans = (a * X[V] + b) % MOD; cout << ans << '\n'; } else if (type == 2) { int V, K; long long C, D; cin >> V >> K >> C >> D; update_range(1, 1, N, in[V], in[V], C, D); for (int u : adj[V]) { update_range(1, 1, N, in[u], in[u], C, D); } } else if (type == 3) { int V; long long C, D; cin >> V >> C >> D; update_range(1, 1, N, in[V], out[V], C, D); } } return 0; }