#include<vector>
#include<algorithm>
#include<functional>
using namespace std;

template<typename T, typename U>
class SegmentTree{
    int n;
    vector<T> node;

    using F = function<T(T, T)>;
    using G = function<T(T, U)>;

    F f;
    G g;
    T en;

public:
    SegmentTree(int n_, F f_, G g_, T en_){
        init(n_, f_, g_, en_);
    }

    SegmentTree(const vector<T>& dat, F f_, G g_, T en_){
        build(dat, f_, g_, en_);
    }

    void init(int n_, F f_, G g_, T en_){
        n = 1;
        while(n < n_){
            n <<= 1;
        }
        f = f_;
        g = g_;
        en = en_;

        node.resize(n << 1);
        fill(node.begin(), node.end(), en);

        return;
    }

    void build(const vector<T>& dat, F f_, G g_, T en_){
        int n_ = (int)dat.size();

        init(n_, f_, g_, en_);

        for(int i = 0 ; i < n_ ; ++i){
            node[i + n] = dat[i];
        }

        for(int i = n - 1 ; 0 < i ; --i){
            node[i] = f(node[i << 1], node[(i << 1) | 1]);
        }

        return;
    }

    void update(int k, U x){
        k += n;
        node[k] = g(node[k], x);

        while(k >>= 1){
            node[k] = f(node[k << 1], node[(k << 1) | 1]);
        }

        return;
    }

    T get(int l, int r){
        l += n;
        r += n;

        T res = en;
        while(l < r){
            if(l & 1){
                res = f(res, node[l++]);
            }
            l >>= 1;
            if(r & 1){
                res = f(res, node[--r]);
            }
            r >>= 1;
        }

        return res;
    }
};

#include<iostream>
#include<map>
#include<utility>
using namespace std;

using lint = long long;

template<typename T>
int compress(vector<T> v, map<T, int> &zip, vector<T> &unzip){
    sort(v.begin(), v.end());
    // v.erase(unique(v.begin(), v.end()), v.end());
    unzip.resize(v.size());
    for(int i = 0, i_len = (int)v.size() ; i < i_len ; ++i){
        zip[v[i]] = i;
        unzip[i] = v[i];
    }
    return (int)v.size();
}

template<typename T>
T meguru_search(T ok, T ng, function<bool(T)> check){
    while(max(ok, ng) - min(ok, ng) > T(1)){
        T mid = (ok + ng) / T(2);
        if(check(mid)){
            ok = mid;
        }else{
            ng = mid;
        }
    }
    return ok;
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);

    int q;
    cin >> q;

    vector< pair< int, pair<lint, lint> > > v;
    vector< pair<lint, lint> > x;

    for(int i = 0 ; i < q ; ++i){
        int com;
        lint a = -1;
        lint b = -1;
        cin >> com;

        if(com == 1){
            cin >> a >> b;
        }

        v.push_back({com, {a, b}});
        x.push_back({a, b});
    }

    map<pair<lint, lint>, int> zip;
    vector< pair<lint, lint> > unzip;
    int n = compress(x, zip, unzip);

    SegmentTree<int, int> seg1(n, [](int l, int r){ return l + r; }, [](int l, int r){ return l + r; }, 0);
    SegmentTree<lint, lint> seg2(n, [](lint l, lint r){ return l + r; }, [](lint l, lint r){ return l + r; }, 0LL);
    lint sum = 0;
    int cnt = 0;
    map< pair<lint, lint>, int > mp;

    for(int i = 0 ; i < q ; ++i){
        if(v[i].first == 1){
            seg1.update(zip[v[i].second] - mp[v[i].second], 1);
            seg2.update(zip[v[i].second] - mp[v[i].second], v[i].second.first);
            sum += v[i].second.second;
            ++cnt;
            ++mp[v[i].second];
        }else if(v[i].first == 2){
            int k = meguru_search<int>(0, n, [&](int mid){ return seg1.get(0, mid) < (cnt + 1) / 2; });
            cout << unzip[k].first << " ";
            if(cnt % 2 == 0){
                cout << sum - seg2.get(0, k + 1) + seg2.get(k + 1, n) << endl;
            }else{
                cout << sum - seg2.get(0, k) + seg2.get(k + 1, n) << endl;
            }
        }
    }

    return 0;
}

Measured memory_bytes: 32612