#include <bits/stdc++.h>

#include <boost/concept_check.hpp>
#include <functional>
#include <vector>

template <
    typename T,
    typename F,
    typename LazyT = T,
    typename LazyApply = T (*)(const T&, const LazyT&, int, int),
    typename LazyAdd = LazyT (*)(const LazyT&, const LazyT&)>
class segtree {
  BOOST_CLASS_REQUIRE2(F, std::function<T(T&, T&)>, boost, ConvertibleConcept);
  BOOST_CLASS_REQUIRE2(LazyApply, std::function<T(T&, LazyT&, int, int)>, boost, ConvertibleConcept);
  BOOST_CLASS_REQUIRE2(LazyAdd, std::function<LazyT(LazyT&, LazyT&)>, boost, ConvertibleConcept);

  const int n;
  const F f;
  const T fIdentity;
  const LazyApply lazyApply;
  const LazyAdd lazyAdd;

  std::vector<T> data;
  std::vector<LazyT> lazyData;
  std::vector<bool> lazyflag;

  int dataLength(int n) {
    int res = 2;
    while (res < n) res = res << 1;
    return res;
  }

  void recalcData(int p, int pBegin, int pEnd, bool recurseToTop = false) {
    data[p] = f(data[(p << 1) + 1], data[(p << 1) + 2]);
    if (lazyflag[p]) data[p] = lazyApply(data[p], lazyData[p], pBegin, pEnd);
    if (recurseToTop && p > 0) {
      int pSize = pEnd - pBegin;
      recalcData((p - 1) >> 1, p & 1 ? pBegin : pBegin - pSize, p & 1 ? pEnd + pSize : pEnd, true);
    }
  }

  void _updateLazy(int begin, int end, const LazyT& value, int p, int pBegin, int pEnd) {
    if (begin <= pBegin && pEnd <= end) {
      addLazyData(p, pBegin, pEnd, value);
    } else if (pBegin < end && begin < pEnd) {
      evalLazy(p, pBegin, pEnd);
      int pCenter = (pBegin + pEnd) >> 1;
      _updateLazy(begin, end, value, (p << 1) + 1, pBegin, pCenter);
      _updateLazy(begin, end, value, (p << 1) + 2, pCenter, pEnd);
      recalcData(p, pBegin, pEnd, false);
    }
  }

  void addLazyData(int p, int pBegin, int pEnd, const LazyT& value) {
    data[p] = lazyApply(data[p], value, pBegin, pEnd);
    lazyData[p] = lazyflag[p]
                      ? lazyAdd(lazyData[p], value)
                      : value;
    lazyflag[p] = true;
  }

  void evalLazy(int p, int pBegin, int pEnd) {
    if (!lazyflag[p]) return;
    int pCenter = (pBegin + pEnd) >> 1;
    addLazyData((p << 1) + 1, pBegin, pCenter, lazyData[p]);
    addLazyData((p << 1) + 2, pCenter, pEnd, lazyData[p]);
    lazyflag[p] = false;
  }

  T _calc(int begin, int end, int p, int pBegin, int pEnd) {
    if (begin <= pBegin && pEnd <= end) {
      return data[p];
    } else if (end <= pBegin || pEnd <= begin) {
      return fIdentity;
    } else {
      evalLazy(p, pBegin, pEnd);
      int pCenter = (pBegin + pEnd) >> 1;
      return f(
          _calc(begin, end, (p << 1) + 1, pBegin, pCenter),
          _calc(begin, end, (p << 1) + 2, pCenter, pEnd));
    }
  }

 public:
  segtree(
      int n,
      F f,
      T fIdentity,
      LazyApply lazyApply = nullptr,
      LazyAdd lazyAdd = nullptr,
      LazyT _someValueOfLazyT = LazyT() /* LazyT謗ｨ隲也畑 */)
      : n(dataLength(n)),
        f(f),
        fIdentity(fIdentity),
        lazyApply(lazyApply),
        lazyAdd(lazyAdd) {
    data.resize(2 * this->n - 1);
    lazyData.resize(2 * this->n - 1);
    lazyflag.resize(2 * this->n - 1);
    for (int i = 0; i < 2 * this->n - 1; ++i) data[i] = fIdentity;
  }

  void update(int index, const T& value) {
    int p = n + index - 1;
    data[p] = value;
    recalcData((p - 1) >> 1, index - 1 + (p & 1), index + 1 + (p & 1), true);
  }

  void updateLazy(int begin, int end, const LazyT& value) {
    _updateLazy(begin, end, value, 0, 0, n);
  }

  T operator()(int begin, int end) {
    return _calc(begin, end, 0, 0, n);
  }
};

// #LIB#

using namespace std;
using ll = long long;
#define double long double
#define rep(i, n) for (long long i = 0; i < (n); ++i)
#define repr(i, a, b) for (auto i = (a); i < (b); ++i)
#define itr(x, c) for (auto&& x : (c))
#define updatemax(t, v) ((t) = std::max((t), (v)))
#define updatemin(t, v) ((t) = std::min((t), (v)))
#define endl _endl
const char _endl = (cin.tie(0), cout.tie(0), ios::sync_with_stdio(0), cout.precision(16), '\n');

using pll = pair<ll, ll>;
pll operator+(const pll& l, const pll& r) {
  return pll(l.first + r.first, l.second + r.second);
}
pll operator*(const pll& l, const ll& r) {
  return pll(l.first * r, l.second * r);
}

int main() {
  ll qlen;
  cin >> qlen;
  vector<tuple<ll, ll, ll>> qs;
  set<ll> as_set;
  rep(i, qlen) {
    ll t;
    cin >> t;
    if (t == 1) {
      ll a, b;
      cin >> a >> b;
      as_set.insert(a);
      qs.emplace_back(t, a, b);
    } else {
      qs.emplace_back(2, -1, -1);
    }
  }
  vector<ll> as;
  itr(a, as_set) as.push_back(a);
  ll alen = as.size();
  vector<ll> qi_to_ai(qlen, -1);
  rep(i, qlen) {
    auto [t, a, b] = qs[i];
    if (t != 1) continue;
    qi_to_ai[i] = lower_bound(as.begin(), as.end(), a) - as.begin();
  }
  segtree st(
      alen + 1,
      [](const pll& a, const pll& b) { return a + b; },
      pll(0, 0),
      [](const pll& a, const pll& l, int b, int e) { return a + l * (e - b); },
      [](const pll& a, const pll& l) { return a + l; });
  rep(i, qlen) {
    auto [t, a, b] = qs[i];
    if (t == 1) {
      ll ai = qi_to_ai[i];
      pll fleft(-1, a + b), fright(1, -a + b);
      st.updateLazy(0, ai + 1, fleft);
      st.updateLazy(ai + 1, alen + 1, fright);
      // rep(i, alen + 1) {
      //   auto [stia, stib] = st(i, i + 1);
      //   cout << stia << "x" << (stib >= 0 ? "+" : "") << stib << " ";
      // }
      // cout << endl;
    } else {
      ll low = 0, high = alen + 1;
      while (high - low > 1) {
        ll middle = (low + high) / 2;
        bool cond = st(middle, middle + 1).first >= 0;
        (cond ? high : low) = middle;
      }
      tie(a, b) = st(high, high + 1);
      ll x = as[high - 1];
      cout << x << ' ' << a * x + b << endl;
    }
  }
}


Measured memory_bytes: 24264