#include <bits/stdc++.h>

namespace BST {
    template <typename T>
    struct Node {
        Node *lch, *rch;
        T val;
        T pri;
        T sum;
        int cnt;

        Node() {}
        Node(T val, T pri) : lch(nullptr), rch(nullptr), val(val), pri(pri), sum(val), cnt(1) {}
    };

    template <typename T>
    struct NodePool {
    private:
        int pool_size;
        std::allocator<Node<T>> alc;
        Node<T> *v;
        std::mt19937 engine;
        std::uniform_int_distribution<T> dist;
        int pos;

    public:
        NodePool(int size) : 
            pool_size(size),
            v(alc.allocate(pool_size)),
            engine(std::chrono::steady_clock::now().time_since_epoch().count()),
            dist(std::numeric_limits<T>::min(), std::numeric_limits<T>::max()),
            pos(0) {}

        ~NodePool() {
            alc.deallocate(v, pool_size);
        }

        Node<T> *alloc(T val) {
            return new(v + pos++) Node<T>(val, dist(engine));
        }
    };

    template <typename T>
    int count(Node<T> *t) { return t ? t->cnt : 0; }
    template <typename T>
    T sum(Node<T> *t) { return t ? t->sum : 0; }

    template <typename T>
    Node<T> *update(Node<T> *t) {
        t->cnt = count(t->lch) + count(t->rch) + 1;
        t->sum = sum(t->lch) + sum(t->rch) + t->val;
        return t;
    }

    template <typename T>
    Node<T> *merge(Node<T> *l, Node<T> *r) {
        if (!l || !r) return l ? l : r;

        if (l->pri > r->pri) {
            l->rch = merge(l->rch, r);
            return update(l);
        } else {
            r->lch = merge(l, r->lch);
            return update(r);
        }
    }

    // count-based: [0, k), [k, n)
    template <typename T>
    std::pair<Node<T>*, Node<T>*> split(Node<T> *t, int k) {
        if (!t) return { nullptr, nullptr };

        if (k <= count(t->lch)) {
            auto s = split(t->lch, k);
            t->lch = s.second;
            return { s.first, update(t) };
        } else {
            auto s = split(t->rch, k - count(t->lch) - 1);
            t->rch = s.first;
            return { update(t), s.second };
        }
    }

    template <typename T>
    T kth_element(Node<T> *t, const int k) {
        if (!t) return std::numeric_limits<T>::max();
        if (k == count(t->lch)) return t->val;
        if (k < count(t->lch)) return kth_element(t->lch, k);
        else return kth_element(t->rch, k - count(t->lch) - 1);
    }

    // returns index of lower_bound of x in t
    template <typename T>
    int lower_bound(const Node<T> * const t, const T x) {
        if (!t) return 0;
        if (x <= t->val) return lower_bound(t->lch, x);
        else return count(t->lch) + 1 + lower_bound(t->rch, x);
    }

    template <typename T>
    int upper_bound(const Node<T> * const t, const T x) {
        if (!t) return 0;
        if (x < t->val) return upper_bound(t->lch, x);
        else return count(t->lch) + 1 + upper_bound(t->rch, x);
    }

    template <typename T>
    struct BinarySearchTree {
        NodePool<T> pool;
        Node<T> *root;

        BinarySearchTree(int size) : pool(size), root(nullptr) {}
        T kth_element(int k) const { return BST::kth_element(root, k); }
        int size() const { return count(root); }
        T sum(int a, int b) {
            // [a, b)
            auto s = split(root, a);
            auto t = split(s.second, b - a);
            auto ret = BST::sum(t.first);
            root = merge(s.first, merge(t.first, t.second));
            return ret;
        }
    };

    template <typename T>
    struct OrderedMultiSet : public BinarySearchTree<T> {
        OrderedMultiSet(int size) : BinarySearchTree<T>(size) {}

        int count(const T val) const {
            return upper_bound(this->root, val) - lower_bound(this->root, val);
        }

        void insert(const T val) {
            int k = lower_bound(this->root, val);
            auto s = split(this->root, k);
            this->root = merge(merge(s.first, this->pool.alloc(val)), s.second);
        }

        void erase(const T val) {
            int lb = lower_bound(this->root, val), ub = upper_bound(this->root, val);
            if (lb == ub) return;
            auto s = split(this->root, lb);
            auto t = split(s, ub - lb);
            this->root = merge(s.first, t.second);
        }
    };
}

using i64 = long long;
using Tree = BST::OrderedMultiSet<i64>;

int main() {
    int q;
    std::cin >> q;
    i64 sb = 0, sa = 0;
    Tree tree(202020);
    while (q--) {
        int t;
        std::cin >> t;
        if (t == 1) {
            i64 a, b;
            std::cin >> a >> b;
            sa += a;
            sb += b;
            tree.insert(a);
        } else {
            int c = tree.size();
            i64 m = (c - 1) / 2;
            auto x = tree.kth_element(m);
            auto sl = tree.sum(0, m + 1);
            auto sr = sa - sl;
            auto ss = (m + 1) * x - sl + sr - (c - m - 1) * x;
            std::cout << x << " " << ss + sb << std::endl;
        }
    }
}


Measured memory_bytes: 9600