#pragma region Macro
#pragma region Basic
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
#define REP(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i)
#define FOR(i, a, b) for (int i = (a), i##_len = (b); i < i##_len; i++)
#define FORD(i, a, b) for (int i = (a), i##_len = (b); i > i##_len; i--)
#define FORR(t, a) for (auto t : a)
#define ALL(x) (x).begin(), (x).end()  // sortなどの引数を省略したい
#define GET(i, j) get<j>(i)
#define MT(x, ...) make_tuple(x, __VA_ARGS__)
#define SZ(x) ((int)(x).size())
//#define ZERO(x) memset(x, 0, sizeof(x))
//#define FILL(x, y) memset(x, y, sizeof(x))
#define UNUSED(x) (void(x));
#define PB push_back
#define EB emplace_back
#ifdef _DEBUG
#define PRE_COMMAND             \
    std::cin.rdbuf(in.rdbuf()); \
    cout << fixed << setprecision(15);
#else
#define PRE_COMMAND cout << fixed << setprecision(15);
#endif
const double EPS = 1e-10;
const double PI = acos(-1.0);
template <class T>
auto MAX(T& seq) {
    return *max_element(seq.begin(), seq.end());
}
template <class T>
auto MIN(T& seq) {
    return *min_element(seq.begin(), seq.end());
}
template <class T>
auto SUM(T& seq) {
    T temp{0};
    auto& temp2 = temp[0];
    return accumulate(seq.begin(), seq.end(), temp2);
}
template <class T>
void SORT(T& seq) {
    sort(seq.begin(), seq.end());
}
template <class T, class S>
void SORT(T& seq, S& sort_order) {
    sort(seq.begin(), seq.end(), sort_order);
}
template <class T>
void SORTR(vector<T>& seq) {
    sort(seq.begin(), seq.end(), greater<T>());
}
template <class T>
void CHMAX(T& a, const T& b) {
    if (a < b) { a = b; }
}
template <class T>
void CHMIN(T& a, const T& b) {
    if (b < a) { a = b; }
}
template <class T>
set<T> VECTOR_2_SET(vector<T>& v) {
    set<T> s;
    for (auto ele : v) { s.insert(ele); }
    return s;
}
template <class T>
vector<T> SET_2_VECTOR(set<T>& s) {
    vector<T> v;
    for (auto ele : s) { v.push_back(ele); }
    return v;
}
#pragma endregion Basic
#pragma region overload
template <class T, class S>
void operator+=(vector<T>& l, S& r) {
    for (auto i : r) { l.push_back(i); }
}
template <class T, class S>
void operator+=(set<T>& l, S& r) {
    for (auto i : r) { l.insert(i); }
}
template <class T, class S>
void operator+=(multiset<T>& l, S& r) {
    for (auto i : r) { l.insert(i); }
}
template <class T, class S>
vector<T> operator+(vector<T>& l, S& r) {
    vector<T> l_copy = l;
    for (auto i : r) { l_copy.push_back(i); }
    return l_copy;
}
template <class T>
vector<T> operator+(const vector<T> l, const vector<T>& r) {
    vector<T> l_copy = l;
    for (auto i : r) { l_copy.push_back(i); }
    return l_copy;
}
template <class T, class S>
set<T> operator+(set<T>& l, S& r) {
    set<T> l_copy = l;
    for (auto i : r) { l_copy.insert(i); }
    return l_copy;
}
template <class T>
set<T> operator+(const set<T> l, const set<T>& r) {
    set<T> l_copy = l;
    for (auto i : r) { l_copy.insert(i); }
    return l_copy;
}
template <class T, class S>
multiset<T> operator+(multiset<T>& l, S& r) {
    set<T> l_copy = l;
    for (auto i : r) { l_copy.insert(i); }
    return l_copy;
}
template <class T>
multiset<T> operator+(const multiset<T> l, const set<T>& r) {
    set<T> l_copy = l;
    for (auto i : r) { l_copy.insert(i); }
    return l_copy;
}
string operator+(const string l, const string& r) {
    string str = l;
    str += r;
    return str;
}
string operator*(const string l, const size_t& r) {
    string str = l;
    for (size_t i = 0; i < r; i++) { str += l; }
    return str;
}
#pragma endregion overload
#pragma region Input
template <class Head>
void INPUT(vector<Head>& head);
template <size_t N, class Head>
void INPUT(array<Head, N>& head);
template <class T1>
void INPUT(tuple<T1>& t);
template <class T1, class T2>
void INPUT(tuple<T1, T2>& t);
template <class T1, class T2, class T3>
void INPUT(tuple<T1, T2, T3>& t);
template <class T1, class T2, class T3, class T4>
void INPUT(tuple<T1, T2, T3, T4>& t);
template <class T1, class T2, class T3, class T4, class T5>
void INPUT(tuple<T1, T2, T3, T4, T5>& t);
template <class Head>
void INPUT(Head& head);
template <class Head, class... Tail>
void INPUT(Head& head, Tail&... tail);
//本体
template <class Head>
void INPUT(vector<Head>& head) {
    for (size_t i = 0; i < head.size(); i++) { INPUT(head[i]); }
}
template <size_t N, class Head>
void INPUT(array<Head, N>& head) {
    for (size_t i = 0; i < head.size(); i++) { INPUT(head[i]); }
}
template <class T1>
void INPUT(tuple<T1>& t) {
    cin >> get<0>(t);
}
template <class T1, class T2>
void INPUT(tuple<T1, T2>& t) {
    cin >> get<0>(t) >> get<1>(t);
}
template <class T1, class T2, class T3>
void INPUT(tuple<T1, T2, T3>& t) {
    cin >> get<0>(t) >> get<1>(t) >> get<2>(t);
}
template <class T1, class T2, class T3, class T4>
void INPUT(tuple<T1, T2, T3, T4>& t) {
    cin >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);
}
template <class T1, class T2, class T3, class T4, class T5>
void INPUT(tuple<T1, T2, T3, T4, T5>& t) {
    cin >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t) >> get<4>(t);
}
template <class Head>
void INPUT(Head& head) {
    cin >> head;
}
template <class Head, class... Tail>
void INPUT(Head& head, Tail&... tail) {
    INPUT(head);
    INPUT((tail)...);
}
#pragma endregion Input
#pragma region Print
template <class T1>
void PRINT2(tuple<T1> t);
template <class T1, class T2>
void PRINT2(tuple<T1, T2> t);
template <class T1, class T2, class T3>
void PRINT2(tuple<T1, T2, T3> t);
template <class T1, class T2, class T3, class T4>
void PRINT2(tuple<T1, T2, T3, T4> t);
template <class T1, class T2, class T3, class T4, class T5>
void PRINT2(tuple<T1, T2, T3, T4, T5> t);
template <class Head>
void PRINT2(vector<Head> head);
template <class Head>
void PRINT2(vector<vector<Head>> head);
template <size_t N, class Head>
void PRINT2(vector<array<Head, N>> head);
template <class... Head>
void PRINT2(vector<tuple<Head...>> head);
template <size_t N, class Head>
void PRINT2(array<Head, N> head);
template <class Head>
void PRINT2(Head head);
template <class Head, class... Tail>
void PRINT2(Head head, Tail... tail);
template <class Head>
void PRINT(Head head);
template <class... Head>
void PRINT(Head... head);
template <int N, class Head>
void PRINT(Head head);
template <class T1>
void PRINT2(tuple<T1> t) {
    PRINT2(get<0>(t));
}
template <class T1, class T2>
void PRINT2(tuple<T1, T2> t) {
    PRINT2(get<0>(t), get<1>(t));
}
template <class T1, class T2, class T3>
void PRINT2(tuple<T1, T2, T3> t) {
    PRINT2(get<0>(t), get<1>(t), get<2>(t));
}
template <class T1, class T2, class T3, class T4>
void PRINT2(tuple<T1, T2, T3, T4> t) {
    PRINT2(get<0>(t), get<1>(t), get<2>(t), get<3>(t));
}
template <class T1, class T2, class T3, class T4, class T5>
void PRINT2(tuple<T1, T2, T3, T4, T5> t) {
    PRINT2(get<0>(t), get<1>(t), get<2>(t), get<3>(t), get<4>(t));
}
template <class Head>
void PRINT2(vector<Head> head) {
    for (auto i = head.begin(); i != head.end(); i++) {
        PRINT2(*i);
        if (i != head.end() - 1) { cout << " "; }
    }
}
template <class Head>
void PRINT2(vector<vector<Head>> head) {
    for (auto i = head.begin(); i != head.end(); i++) {
        PRINT2(*i);
        if (i != head.end() - 1) { cout << endl; }
    }
}
template <size_t N, class Head>
void PRINT2(vector<array<Head, N>> head) {
    for (auto i = head.begin(); i != head.end(); i++) {
        PRINT2(*i);
        if (i != head.end() - 1) { cout << endl; }
    }
}
template <class... Head>
void PRINT2(vector<tuple<Head...>> head) {
    for (auto i = head.begin(); i != head.end(); i++) {
        PRINT2(*i);
        if (i != head.end() - 1) { cout << endl; }
    }
}
template <size_t N, class Head>
void PRINT2(array<Head, N> head) {
    for (auto i = head.begin(); i != head.end(); i++) {
        PRINT2(*i);
        if (i != head.end() - 1) { cout << " "; }
    }
}
template <class Head>
void PRINT2(Head head) {
    cout << head;
}
template <class Head, class... Tail>
void PRINT2(Head head, Tail... tail) {
    PRINT2(head);
    cout << " ";
    PRINT2((tail)...);
}
template <class Head>
void PRINT(Head head) {
    PRINT2(head);
    cout << endl;
}
template <class... Head>
void PRINT(Head... head) {
    PRINT2((head)...);
    cout << endl;
}
template <int N, class Head>
void PRINT(Head head) {
    PRINT2(head);
    cout << endl;
}
#pragma endregion Print
#pragma endregion Macro

// ini：上限（下限）,base：元の配列,monoid：モノイド,tree：セグ木,depth：treeの深さ,
// basesize：baseの要素数,treesize：treeの要素数,num：treesize-basesize
// 初期値（上限とか下限）を決定
template <class num_type>
struct segtree {
    // monoid→2つのノードを結合させる関数
    // operate→updateによる区間に対する作用の関数
    // modify→lazyをスケール変換する関数
    int num, depth, basesize, treesize;
    vector<num_type> base, tree, lazy;
    // #####  monoidのiniの設定  #####
    // 区間和のとき
    num_type ini = 0;
    // 区間最小値のとき
    // num_type ini = pow(2, 31) - 1;

    // 区間和のとき
    num_type monoid(num_type& x, num_type& y) { return x + y; }
    num_type modify(int width, num_type& value) { return width * value; }
    // 区間最小値のとき
    // num_type monoid(num_type& x, num_type& y) { return min(x, y); }
    // num_type modify(int width, num_type& value) { UNUSED(width); return
    // value; }

    // 区間加算のとき
    num_type ini_op = 0;
    num_type operate(num_type& x, num_type& y) { return x + y; }
    // 区間更新のとき
    // num_type ini_op = pow(10, 12);
    // num_type operate(num_type& x, num_type& y) { UNUSED(y); return x; }
    // 元の配列, モノイド, 初期値
    segtree(vector<num_type> temp) : base(temp) {
        basesize = (int)base.size();
        num = 1;
        depth = 1;
        while (num < basesize) {
            num *= 2;
            depth++;
        }
        num--;
        treesize = num * 2 + 1;
        tree.assign(treesize, ini);
        lazy.assign(treesize, ini_op);
        for (int i = num; i < num + basesize; i++) { tree[i] = base[i - num]; }
        for (int i = num + basesize; i < treesize; i++) { tree[i] = ini; }
        for (int i = num - 1; i > -1; i--) {
            tree[i] = monoid(tree[2 * i + 1], tree[2 * i + 2]);
        }
    }
    // modifyとoperateを同時に行う関数
    num_type mod_op(int width, int node) {
        if (lazy[node] != ini_op) {
            num_type temp = modify(width, lazy[node]);
            return operate(temp, tree[node]);
        } else {
            return tree[node];
        }
    }
    // 半開区間[lower,upper)の最小値（とか）を探す関数
    num_type search(int lower, int upper) {
        num_type ret = ini, temp;
        vector<tuple<int, int, int>> stack(1, make_tuple(0, num + 1, 0));
        int l, r, m, node;
        while (stack.size()) {
            tie(l, r, node) = stack.back();
            stack.pop_back();
            m = (l + r) / 2;
            if (lower <= l && r <= upper) {
                temp = mod_op(r - l, node);
                ret = monoid(ret, temp);
            } else {
                eval(l, r, node);
                if (upper <= m) {
                    stack.push_back(make_tuple(l, m, node * 2 + 1));
                } else if (m <= lower) {
                    stack.push_back(make_tuple(m, r, node * 2 + 2));
                } else {
                    stack.push_back(make_tuple(l, m, node * 2 + 1));
                    stack.push_back(make_tuple(m, r, node * 2 + 2));
                }
            }
        }
        return ret;
    }
    // 葉方向に伝播させる関数
    void eval(int& l, int& r, int& node) {
        if (lazy[node] != ini_op) {
            if (2 * node + 1 < treesize) {
                if (num <= node * 2 + 1) {
                    tree[node * 2 + 1] =
                        operate(lazy[node], tree[node * 2 + 1]);
                    tree[node * 2 + 2] =
                        operate(lazy[node], tree[node * 2 + 2]);
                } else {
                    lazy[node * 2 + 1] =
                        operate(lazy[node], lazy[node * 2 + 1]);
                    lazy[node * 2 + 2] =
                        operate(lazy[node], lazy[node * 2 + 2]);
                }
            }
            num_type temp = modify(r - l, lazy[node]);
            tree[node] = operate(temp, tree[node]);
            lazy[node] = ini_op;
        }
    }
    // base[l:r)をsに更新してセグ木全体を更新する関数
    void update(int lower, int upper, num_type new_value) {
        vector<tuple<int, int, int>> stack(1, make_tuple(0, num + 1, 0));
        set<tuple<int, int>> nodeset;
        int l, r, m, node, parent, width;
        num_type value;
        while (stack.size()) {
            tie(l, r, node) = stack.back();
            stack.pop_back();
            m = (l + r) / 2;
            width = r - l;
            if (lower <= l && r <= upper) {
                lazy[node] = operate(new_value, lazy[node]);
                value = modify(width, new_value);
                if (node != 0) {
                    parent = (node - 1) / 2;
                    nodeset.insert(make_tuple(parent, width));
                }
                if (width == 1) {
                    value = modify(width, value);
                    tree[node] = operate(value, tree[node]);
                    lazy[node] = ini_op;
                }
            } else {
                eval(l, r, node);
                if (upper <= m) {
                    stack.push_back(make_tuple(l, m, node * 2 + 1));
                } else if (m <= lower) {
                    stack.push_back(make_tuple(m, r, node * 2 + 2));
                } else {
                    stack.push_back(make_tuple(l, m, node * 2 + 1));
                    stack.push_back(make_tuple(m, r, node * 2 + 2));
                }
            }
        }
        num_type tmp1, tmp2;
        while (nodeset.size()) {
            tie(node, width) = *rbegin(nodeset);
            nodeset.erase(make_tuple(node, width));
            tmp1 = mod_op(width, node * 2 + 1);
            tmp2 = mod_op(width, node * 2 + 2);
            tree[node] = monoid(tmp1, tmp2);
            if (node != 0) {
                nodeset.insert(make_tuple((node - 1) >> 1, width << 1));
            }
        }
    }
};

template <class num_type>
struct HLD {
    // iniとmonoidの設定
    num_type ini = 0;
    num_type monoid(num_type& x, num_type y) { return x + y; }

    int root, n, nlog2, HL_size;
    vector<int> d;
    vector<vector<int>> tree, HL_tree, parent;
    vector<tuple<int, int>> HL_position;
    vector<segtree<num_type>> seg;
    HLD(vector<vector<int>>& t1, vector<num_type>& base, int t2) {
        tree = t1;
        root = t2, n = (int)tree.size();
        HL_position.assign(n, make_tuple(0, 0));
        nlog2 = log2(n);
        d.assign(n, -1);
        d[root] = 0;
        int cnt = 0;
        vector<int> q(1, root), qq;
        // 根からの距離を求める
        while (q.size()) {
            cnt++;
            qq = {};
            while (q.size()) {
                int u = q.back();
                q.pop_back();
                for (int v : tree[u]) {
                    if (d[v] == -1) {
                        d[v] = cnt;
                        qq.push_back(v);
                    }
                }
            }
            q = qq;
        }
        // LCA部分の前処理
        parent.assign(n, {});
        for (int u = 0; u < n; u++) {
            bool flag = true;
            for (int v : tree[u]) {
                if (d[u] > d[v]) {
                    parent[u].push_back(v);
                    flag = false;
                    break;
                }
            }
            if (flag) { parent[u].push_back(-1); }
        }
        for (int c = 0; c < nlog2; c++) {
            for (int u = 0; u < n; u++) {
                if (parent[u].back() == -1) {
                    parent[u].push_back(-1);
                } else {
                    parent[u].push_back(parent[parent[u].back()][c]);
                }
            }
        }
        // HL分解の前処理
        vector<int> subtree_size(n, 1);
        vector<tuple<int, int>> d2(n);
        for (int u = 0; u < n; u++) { d2[u] = make_tuple(-d[u], u); }
        sort(d2.begin(), d2.end());
        for (tuple<int, int> temp : d2) {
            int u = get<1>(temp);
            int dist = d[u];
            int temp2 = 0;
            for (int v : tree[u]) {
                if (d[v] > dist) { temp2 += subtree_size[v]; }
            }
            subtree_size[u] += temp2;
        }
        vector<int> heavy_stack, heavy_temp;
        vector<tuple<int, int>> next_wv;
        heavy_stack.push_back(root);
        while (heavy_stack.size()) {
            int u = heavy_stack.back();
            heavy_stack.pop_back();
            heavy_temp.push_back(u);
            while (true) {
                next_wv = {};
                int dist = d[u];
                for (int v : tree[u]) {
                    if (d[v] > dist) {
                        next_wv.push_back(make_tuple(subtree_size[v], v));
                    }
                }
                sort(next_wv.begin(), next_wv.end());
                if (next_wv.size()) {
                    int v, w;
                    tie(w, v) = next_wv.back();
                    next_wv.pop_back();
                    heavy_temp.push_back(v);
                    u = v;
                } else {
                    break;
                }
                for (auto temp : next_wv) {
                    int v;
                    v = get<1>(temp);
                    heavy_stack.push_back(v);
                }
            }
            HL_tree.push_back(heavy_temp);
            heavy_temp = {};
        }
        HL_size = (int)HL_tree.size();
        for (int i = 0; i < HL_size; i++) {
            vector<num_type> base_temp;
            int HL_elem_size = (int)HL_tree[i].size();
            for (int j = 0; j < HL_elem_size; j++) {
                HL_position[HL_tree[i][j]] = make_tuple(i, j);
                base_temp.push_back(base[HL_tree[i][j]]);
            }
            segtree<num_type> seg_temp(base_temp);
            seg.push_back(seg_temp);
        }
        // DEBUG(HL_tree);
        // DEBUG(HL_position);
    }

    int log2(int x) {
        int ret = 0, tmp = 2;
        while (tmp <= x) {
            tmp *= 2;
            ret++;
        }
        return ret;
    }

    int lca(int a, int b) {
        if (d[a] < d[b]) { swap(a, b); }
        int rest = d[a] - d[b], rest_log;
        while (rest > 0) {
            rest_log = log2(rest);
            a = parent[a][rest_log];
            rest = rest - (int)pow(2, rest_log);
        }
        int i = nlog2;
        while (i >= 0) {
            if (parent[a][i] == parent[b][i]) {
                i--;
            } else {
                a = parent[a][i];
                b = parent[b][i];
            }
        }
        if (a == b) {
            return a;
        } else {
            return parent[a][0];
        }
    }
    num_type search(int u, int v) {
        num_type ret = ini;
        vector<int> start;
        int anc_i, anc_j, anc;
        anc = lca(u, v);
        tie(anc_i, anc_j) = HL_position[anc];
        if (u == v) {
            ret = seg[anc_i].search(anc_j, anc_j + 1);
            start = {};
        } else if (u == anc) {
            start = {v};
        } else if (v == anc) {
            start = {u};
        } else {
            start = {u, v};
        }
        // DEBUG(start);
        for (int now : start) {
            while (true) {
                int now_i, now_j;
                tie(now_i, now_j) = HL_position[now];
                if (now_i == anc_i) {
                    if (anc_j != now_j) {
                        ret = monoid(ret, seg[now_i].search(anc_j, now_j + 1));
                    }
                    break;
                } else {
                    ret = monoid(ret, seg[now_i].search(0, now_j + 1));
                    now = parent[HL_tree[now_i][0]][0];
                }
            }
        }
        return ret;
    }
    int update(int u, int v, num_type w) {
        int edge = 1;  // 辺を考えるときは1、頂点のとき0
        vector<int> start;
        int anc_i, anc_j, anc;
        anc = lca(u, v);
        tie(anc_i, anc_j) = HL_position[anc];
        if (u == v) {
            if (edge == false) {
                seg[anc_i].update(anc_j + edge, anc_j + 1, w);
            }
            start = {};
        } else if (u == anc) {
            start = {v};
        } else if (v == anc) {
            start = {u};
        } else {
            start = {u, v};
        }
        for (int now : start) {
            while (true) {
                int now_i, now_j;
                tie(now_i, now_j) = HL_position[now];
                if (now_i == anc_i) {
                    if (anc_j + edge < now_j + 1) {
                        seg[now_i].update(anc_j + edge, now_j + 1, w);
                    }
                    break;
                } else {
                    seg[now_i].update(0, now_j + 1, w);
                    now = parent[HL_tree[now_i][0]][0];
                }
            }
        }
        return 0;
    }
};

int main() {
    PRE_COMMAND
    int n, x, k, q;
    ll y;
    INPUT(n);
    vector<vector<int>> g(n);
    vector<ll> base(n, 0);
    for (int i = 0; i < n; i++) {
        cin >> k;
        for (int j = 0; j < k; j++) {
            cin >> x;
            g[i].push_back(x);
            g[x].push_back(i);
        }
    }
    INPUT(q);
    HLD<ll> hld(g, base, 0);
    REP(i, q) {
        INPUT(k, x);
        if (k == 0) {
            INPUT(y);
            hld.update(0, x, y);
        } else {
            PRINT(hld.search(0, x));
        }
    }
}


Measured memory_bytes: 48936