#include using namespace std; const int N = 1e5 + 15, K = 15, mod = 998244353; int n, q, k, a[N], dep[N], siz[N], top[N], ffa[N], nod[N], kth[N]; int dfn[N], in[N][2], ou[N][2], idx, in2[N][K], ou2[N][K], sp[N][K]; vector e[N], poss[N][K]; struct Fun { long long k, b; Fun friend operator * (Fun A, Fun B) { return {A.k * B.k % mod, (A.b * B.k + B.b) % mod}; } }; struct SegTree { static const int SN = N * 4; Fun val[SN]; void build(int x = 1, int l = 1, int r = n) { if (l == r) { return val[x] = {0, a[nod[l]]}, void(); } val[x] = {1, 0}; int mid = (l + r) / 2; build(x * 2, l, mid); build(x * 2 + 1, mid + 1, r); } void pushDown(int x) { val[x * 2] = val[x * 2] * val[x]; val[x * 2 + 1] = val[x * 2 + 1] * val[x]; val[x] = {1, 0}; } void modify(int L, int R, Fun v, int x = 1, int l = 1, int r = n) { if (l > R || r < L) { return; } if (l >= L && r <= R) { return val[x] = val[x] * v, void(); } pushDown(x); int mid = (l + r) / 2; modify(L, R, v, x * 2, l, mid); modify(L, R, v, x * 2 + 1, mid + 1, r); } long long ask(int p, int x = 1, int l = 1, int r = n) { if (l == r) { return val[x].b; } pushDown(x); int mid = (l + r) / 2; return mid >= p ? ask(p, x * 2, l, mid) : ask(p, x * 2 + 1, mid + 1, r); } } sgt; void DFS(int x, int fa) { siz[x] = 1; ffa[x] = fa; dep[x] = dep[fa] + 1; if (fa) { e[x].erase(find(e[x].begin(), e[x].end(), fa)); } for (auto &y : e[x]) { DFS(y, x); siz[x] += siz[y]; if (siz[y] > siz[e[x][0]]) { swap(y, e[x][0]); } } } void split(int x) { kth[x] = 1; if (ffa[x] && x == e[ffa[x]][0]) { kth[x] = kth[ffa[x]] + 1; } top[x] = (kth[x] <= k + 1 ? x : top[ffa[x]]); in[x][0] = idx + 1; if (x <= n && kth[x] > k) { nod[dfn[x] = ++idx] = x; } for (auto y : e[x]) { split(y); } ou[x][0] = idx; } void getPoss(int x) { poss[x][0] = {x}; for (auto y : e[x]) { getPoss(y); for (int i = 1; i <= k; i++) { for (auto p : poss[y][i - 1]) { poss[x][i].emplace_back(p); } } } } void giveId(int x) { for (auto y : poss[x][k]) { if (y <= n && kth[y] <= k) { nod[dfn[y] = ++idx] = y; } } in[x][1] = idx + 1; for (auto y : e[x]) { giveId(y); } ou[x][1] = idx; } void disMod(int x, int d, Fun v) { sgt.modify(in2[x][d], ou2[x][d], v); if (kth[sp[x][d]] <= k) { return; } int w = dfn[sp[x][d]]; if (w) { sgt.modify(w, w, v); } } int main() { ios :: sync_with_stdio(false), cin.tie(0); cin >> n >> q; k = 10; for (int i = 1; i < n; i++) { int x, y; cin >> x >> y; e[x].emplace_back(y); e[y].emplace_back(x); } for (int i = 1; i <= n; i++) { cin >> a[i]; } for (int i = n + 1; i <= n + k; i++) { int j = (i == n + 1 ? 1 : i - 1); e[i].emplace_back(j); e[j].emplace_back(i); } int rt = n + k; DFS(rt, 0); split(rt); getPoss(rt); giveId(rt); for (int i = 1; i <= n + k; i++) { for (int j = 0; j <= k; j++) { in2[i][j] = n + 1; ou2[i][j] = 0; for (auto p : poss[i][j]) { if (p > n || kth[p] > k) { continue; } in2[i][j] = min(in2[i][j], dfn[p]); ou2[i][j] = max(ou2[i][j], dfn[p]); } } sp[i][0] = i; for (int j = 1; j <= k; j++) { if (e[sp[i][j - 1]].empty()) { break; } sp[i][j] = e[sp[i][j - 1]][0]; } } sgt.build(); for (int i = 1; i <= q; i++) { int op, x, y, z, w; cin >> op >> x; if (op == 1) { cout << sgt.ask(dfn[x]) << "\n"; } else if (op == 2) { cin >> y >> z >> w; while (y >= 0) { disMod(x, y, {z, w}); if (y) { disMod(x, y - 1, {z, w}); } x = ffa[x]; y--; } } else if (op == 3) { cin >> y >> z; sgt.modify(in[x][0], ou[x][0], {y, z}); sgt.modify(in[x][1], ou[x][1], {y, z}); for (int j = 0; j <= k; j++) { sgt.modify(in2[x][j], ou2[x][j], {y, z}); } } else { cin >> y >> z >> w; while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) { swap(x, y); } sgt.modify(dfn[top[x]], dfn[x], {z, w}); x = ffa[top[x]]; } if (dfn[x] > dfn[y]) { swap(x, y); } sgt.modify(dfn[x], dfn[y], {z, w}); } } return 0; }