#pragma GCC optimize("O3") // (code on steroids)
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
# define int ll
# define fastio ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
# define len(x) (ll((x).size()))

# define LG 24
# define nax 300005


class node{
public:
    int gold; int cost;
    vector <node*> daughters;
    node(int A, int C){
        gold = A;
        cost = C;
        daughters = {};
    }
};


int first_positive_node_above( int currnode , unordered_map<int,node*>& dat , unordered_map<int,vector<int>>& p ){
    if(dat[currnode]->gold==0) return(-1);
    int cn = currnode;
    while(1){
        if(cn==0) break;
        int fl = 0;
        for(int i = LG-1 ; i >= 0 ; i--){
            if ( dat [ p [cn][i] ]->gold ){
                fl=1;
                cn = p[cn][i];
                break;
            }
        }
        if(fl) continue;
        break;
    }
    return(cn);
}

int32_t main(){
    fastio;
    int q,a0,c0;
    cin>>q>>a0>>c0;

    unordered_map< int , vector<int> > p = {};
    p[0] = vector<int> (LG , 0);

    unordered_map<int , node*> dat = {};
    dat[0] = new node(a0,c0);

    for(int query = 1;query<=q;query++){

        int query_type; cin>>query_type;

        // query type to add a new node
        if(query_type==1){
            int par, gold, cost; cin>>par>>gold>>cost;
            node* newnode = new node(gold, cost);
            dat[query] = newnode;
            dat[par]->daughters.push_back(newnode);

            p[query] = vector<int> (LG , -1);
            p[query][0] = par;
            for(int i = 1 ; i < LG ; i++){
                p[query][i] = p[p[query][i-1]][i-1];
            }
        }

        // query type to buy some gold
        if(query_type == 2) {
            int v,w; cin>>v>>w;
            // first, find the first non zero node in [v..0]
            // int currnode = v;

            int amt_purchased = 0;
            int money_spent = 0;

            int rep=0;
            // for( rep = 0 ; rep < int(1e5) ; rep++ )
            while(1)
            {
                // check if we need to proceed
                int parnode = first_positive_node_above(v,dat,p);
                if(parnode==-1) break;
                if(amt_purchased>=w) break;
                int newpurchased = min( w - amt_purchased , dat[parnode]->gold );
                amt_purchased += newpurchased;
                money_spent += (newpurchased)*(dat[parnode]->cost);
                dat[parnode]->gold = dat[parnode]->gold - newpurchased;
            }
            // if(rep > (int(1e5))-100 ) assert(0);

            cout<<amt_purchased<<" "<<money_spent<<endl;

        }

    }

    return(0);
}
