#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
	ll out=0,fh=1;
	char jp=getchar();
	while ((jp>'9'||jp<'0')&&jp!='-')
		jp=getchar();
	if (jp=='-')
		fh=-1,jp=getchar();
	while (jp>='0'&&jp<='9')
		out=out*10+jp-'0',jp=getchar();
	return out*fh;
}
const int MAXN=2e5+10;
struct FhqTreap
{
#define rt treap[o]
#define ls treap[treap[o].lson]
#define rs treap[treap[o].rson]
	int x,y,z,ans;
	int idx;
	FhqTreap()
	{
		x=y=z=0;
		idx=0;
	}
	struct node
	{
		int lson,rson,key,weight,size;
	} treap[MAXN];
	inline int newnode(int key)
	{
		++idx;
		treap[idx].size=1;
		treap[idx].weight=rand();
		treap[idx].key=key;
		return idx;
	}
	inline void pushup(int o)
	{
		rt.size=ls.size+rs.size+1;
	}
	void split(int& x,int& y,int key,int o)//小于等于key的分在x中
	{
		if(!o)
			x=y=0;
		else
		{
			if(rt.key<=key)
			{
				x=o;
				split(rt.rson,y,key,rt.rson);
			}
			else
			{
				y=o;
				split(x,rt.lson,key,rt.lson);
			}
			pushup(o);
		}
	}
	int merge(int x,int y)//合并,保证x的权值小于y的权值. key_x<key_y
	{
		if(x==0||y==0)
			return x+y;
		if(treap[x].weight<treap[y].weight)
		{
			treap[x].rson=merge(treap[x].rson,y);
			pushup(x);
			return x;
		}
		else
		{
			treap[y].lson=merge(x,treap[y].lson);
			pushup(y);
			return y;
		}
	}
	inline int Rank(int&root,int key)//get the node (which key equals to the key)'s rank.
	{
		split(x,y,key-1,root);
		ans=treap[x].size+1;
		root=merge(x,y);
		return ans;
	}
	inline int kth(int o,int rank)// find the id of the node which rank is the rank in the tree which root is o.
	{
		while(1)
		{
			if(ls.size>=rank)
				o=rt.lson;//the answer must be in o's lson,search in it.
			else if(ls.size+1==rank)
				return treap[o].key;//o is the rank'th.
			else
			{
				rank-=ls.size+1;
				o=rt.rson;//cannot find in o and o's lson,search in o's rson.
			}
		}
	}
	inline void Insert(int&root,int key)// insert a node which key is the key in whole the tree.
	{
		split(x,y,key,root);
		root=merge(merge(x,newnode(key)),y);
	}
} T;
ll bsum=0;
int Q,k=0,Rt=0;
struct query
{
	int op,a,b;
}q[MAXN];
int A[MAXN],cnt=0;
struct Segtree
{
	struct node
	{
		ll sum,tot;
		int l,r;
	}Tree[MAXN<<2];
#define root Tree[o]
#define lson Tree[o<<1]
#define rson Tree[o<<1|1]
	void pushup(int o)
	{
		root.sum=lson.sum+rson.sum;
	}
	void BuildTree(int o,int l,int r)
	{
		root.l=l,root.r=r;
		root.sum=0;
		if(l==r)
			return;
		int mid=(l+r)>>1;
		BuildTree(o<<1,l,mid);
		BuildTree(o<<1|1,mid+1,r);
	}
	void upd(int o,int pos,int c)
	{
		int l=root.l,r=root.r;
		if(l==r)
		{
			root.sum+=c;
			return;
		}
		int mid=(l+r)>>1;
		if(pos<=mid)
			upd(o<<1,pos,c);
		else
			upd(o<<1|1,pos,c);
		pushup(o);
	}
	ll query(int o,int L,int R)
	{
		if(L>R)
			return 0;
		int l=root.l,r=root.r;
		if(L<=l && r<=R)
			return root.sum;
		ll res=0;
		int mid=(l+r)>>1;
		if(L<=mid)
			res+=query(o<<1,L,R);
		if(R>mid)
			res+=query(o<<1|1,L,R);
		return res;
	}
}Seg;
int rnk(int x)
{
	return lower_bound(A+1,A+1+cnt,x)-A;
}
int main()
{
	Q=read();
	for(int i=1;i<=Q;++i)
	{
		q[i].op=read();
		if(q[i].op==1)
		{
			A[++cnt]=q[i].a=read();
			q[i].b=read();
		}
	}
	sort(A+1,A+1+cnt);
	cnt=unique(A+1,A+1+cnt)-(A+1);
	Seg.BuildTree(1,1,cnt);
	for(int i=1;i<=Q;++i)
	{
		if(q[i].op==1)
		{
			int a=q[i].a,b=q[i].b;
			++k;
			bsum+=b;
			Seg.upd(1,rnk(a),a);
			T.Insert(Rt,a);
		}
		else
		{
			int rk=(k+1)>>1;
			int x=T.kth(Rt,rk);
			rk=T.Rank(Rt,x);
			int pos=rnk(x);
			ll res=1LL*(rk-1)*x-Seg.query(1,1,pos-1)-1LL*(k-rk+1)*x+Seg.query(1,pos,cnt);
	//		res-=Seg.query(1,pos,pos);
			printf("%d %lld\n",x,res+bsum);
		}
	}
	return 0;
}

Measured memory_bytes: 16896