#include <map>
#include <set>
#include <array>
#include <cmath>
#include <deque>
#include <bitset>
#include <random>
#include <string>
#include <vector>
#include <cassert>
#include <complex>
#include <iomanip>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
using namespace std;
const int MOD = 998244353;
const int MAXN = 200'200;
vector<int> G[MAXN];
int sz[MAXN];
int par[MAXN];
int path_id[MAXN];
int path_ind[MAXN];
vector<int> paths[MAXN];
int tin[MAXN];
int tout[MAXN];
vector<int> order;
const int K = 3;
long long values[MAXN][K];
void dfs_sz(int v) {
sz[v] = 1;
for (int u : G[v]) {
dfs_sz(u);
sz[v] += sz[u];
}
}
void dfs_paths(int v) {
tin[v] = order.size();
order.emplace_back(v);
if (G[v].empty()) {
path_id[v] = v;
} else {
int L = G[v][0], R = G[v][1];
if (sz[L] >= sz[R]) {
dfs_paths(L);
dfs_paths(R);
path_id[v] = path_id[L];
} else {
dfs_paths(R);
dfs_paths(L);
path_id[v] = path_id[R];
}
values[v][0] = (values[L][1] * values[R][2] - values[L][2] * values[R][1]) % MOD;
values[v][1] = (values[L][2] * values[R][0] - values[L][0] * values[R][2]) % MOD;
values[v][2] = (values[L][0] * values[R][1] - values[L][1] * values[R][0]) % MOD;
}
path_ind[v] = paths[path_id[v]].size();
paths[path_id[v]].emplace_back(v);
tout[v] = order.size();
}
void dumbfs(int v) {
if (G[v].empty()) {
} else {
int L = G[v][0], R = G[v][1];
dumbfs(L);
dumbfs(R);
values[v][0] = (values[L][1] * values[R][2] - values[L][2] * values[R][1]) % MOD;
values[v][1] = (values[L][2] * values[R][0] - values[L][0] * values[R][2]) % MOD;
values[v][2] = (values[L][0] * values[R][1] - values[L][1] * values[R][0]) % MOD;
}
}
struct Matrix {
long long vals[K][K];
Matrix() {
clear();
}
void clear() {
for (int i = 0; i < K; ++i)
fill(vals[i], vals[i] + K, 0);
}
};
void multiply(const Matrix& left, const Matrix& right, Matrix& ans) {
ans.clear();
for (int i = 0; i < K; ++i) {
for (int j = 0; j < K; ++j) {
for (int l = 0; l < K; ++l)
ans.vals[i][l] += left.vals[i][j] * right.vals[j][l];
}
}
for (int i = 0; i < K; ++i) {
for (int j = 0; j < K; ++j)
ans.vals[i][j] %= MOD;
}
}
Matrix tree[(1 << 19) + 228];
void build(int v, int left, int right, vector<Matrix>& A) {
if (left + 1 == right) {
tree[v] = A[left];
return;
}
int mid = (left + right) / 2;
build(2 * v + 1, left, mid, A);
build(2 * v + 2, mid, right, A);
multiply(tree[2 * v + 1], tree[2 * v + 2], tree[v]);
}
void upd(int v, int left, int right, int i, const Matrix& val) {
if (left + 1 == right) {
tree[v] = val;
return;
}
int mid = (left + right) / 2;
if (i < mid)
upd(2 * v + 1, left, mid, i, val);
else
upd(2 * v + 2, mid, right, i, val);
multiply(tree[2 * v + 1], tree[2 * v + 2], tree[v]);
}
long long tmp_vals[K];
long long extra_tmp_vals[K];
void mul_ans(int v, int left, int right, int x, int y) {
if (y <= left || right <= x)
return;
if (x <= left && right <= y) {
for (int i = 0; i < K; ++i) {
extra_tmp_vals[i] = 0;
for (int j = 0; j < K; ++j)
extra_tmp_vals[i] += tree[v].vals[i][j] * tmp_vals[j];
extra_tmp_vals[i] %= MOD;
}
for (int i = 0; i < K; ++i)
tmp_vals[i] = extra_tmp_vals[i];
return;
}
int mid = (left + right) / 2;
mul_ans(2 * v + 2, mid, right, x, y);
mul_ans(2 * v + 1, left, mid, x, y);
}
Matrix tmp_mat;
void make_left(long long v[K]) {
tmp_mat.clear();
tmp_mat.vals[0][1] = -v[2];
tmp_mat.vals[0][2] = v[1];
tmp_mat.vals[1][0] = v[2];
tmp_mat.vals[1][2] = -v[0];
tmp_mat.vals[2][0] = -v[1];
tmp_mat.vals[2][1] = v[0];
}
void make_right(long long v[K]) {
tmp_mat.clear();
tmp_mat.vals[0][1] = v[2];
tmp_mat.vals[0][2] = -v[1];
tmp_mat.vals[1][0] = -v[2];
tmp_mat.vals[1][2] = v[0];
tmp_mat.vals[2][0] = v[1];
tmp_mat.vals[2][1] = -v[0];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, q;
cin >> n >> q;
par[0] = -1;
for (int i = 0; i < n; ++i) {
char c;
cin >> c;
if (c == 'x') {
int l, r;
cin >> l >> r;
--l;
--r;
G[i].emplace_back(l);
G[i].emplace_back(r);
par[l] = i;
par[r] = i;
} else {
cin >> values[i][0] >> values[i][1] >> values[i][2];
}
}
dfs_sz(0);
dfs_paths(0);
vector<Matrix> start_vals(n);
Matrix E;
for (int i = 0; i < K; ++i)
E.vals[i][i] = 1;
for (int i = 0; i < n; ++i) {
int v = order[i];
if (G[v].empty()) {
start_vals[i] = E;
} else {
int L = G[v][0], R = G[v][1];
if (sz[L] >= sz[R]) {
make_right(values[R]);
} else {
make_left(values[L]);
}
start_vals[i] = tmp_mat;
}
}
build(0, 0, n, start_vals);
vector<int> leaves;
for (int i = 0; i < n; ++i) {
if (G[i].empty())
leaves.emplace_back(i);
}
while (q--) {
int v;
cin >> v;
--v;
cin >> values[v][0] >> values[v][1] >> values[v][2];
/*v = leaves[rand() % leaves.size()];
values[v][0] = rand() % 10;
values[v][1] = rand() % 10;
values[v][2] = rand() % 10;
cerr << v + 1 << ' ' << values[v][0] << ' ' << values[v][1] << ' ' << values[v][2] << '\n';*/a
while (v != -1) {
int id = path_id[v];
int u = paths[id].back();
// start of the path
int fin = paths[id].front();
for (int i = 0; i < K; ++i)
tmp_vals[i] = values[fin][i];
mul_ans(0, 0, n, tin[u], tin[fin]);
for (int i = 0; i < K; ++i)
values[u][i] = tmp_vals[i];
int p = par[u];
if (p != -1) {
int L = G[p][0], R = G[p][1];
if (u == L) {
make_left(values[u]);
} else {
make_right(values[u]);
}
upd(0, 0, n, tin[p], tmp_mat);
}
v = p;
}
/*int cur_values[K];
for (int i = 0; i < K; ++i)
cur_values[i] = values[0][i];
dumbfs(0);
for (int i = 0; i < K; ++i) {
if ((cur_values[i] - values[0][i]) % MOD != 0) {
cerr << "BUG!!\n";
cerr << "got: ";
for (int j = 0; j < K; ++j)
cerr << cur_values[j] << ' ';
cerr << '\n';
cerr << "need ";
for (int j = 0; j < K; ++j)
cerr << values[0][j] << ' ';
cerr << '\n';
}
assert(cur_values[i] == values[0][i]);
}*/
for (int i = 0; i < K; ++i)
cout << values[0][i] << ' ';
cout << '\n';
}
return 0;
}