use std::collections::BinaryHeap;
use std::io::*;
use std::str::FromStr;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

fn insert(ps: &mut Vec<BinaryHeap<i64>>, offsets: &mut Vec<i64>, a: i64, lr: usize) {
    let la = *ps[0].peek().unwrap();
    let ra = -*ps[1].peek().unwrap();
    if lr == 0 {
        if a <= la {
            offsets[0] += (la - a).abs();
        } else {
            offsets[0] += (a - la).abs() * ps[0].len() as i64;
        }
        ps[0].push(a);
    } else {
        if ra <= a {
            offsets[1] += (a - ra).abs();
        } else {
            offsets[1] += (ra - a).abs() * ps[1].len() as i64;
        }
        ps[1].push(-a);
    }
}

fn push(ps: &mut Vec<BinaryHeap<i64>>, offsets: &mut Vec<i64>, a: i64) {
    if ps[0].len() == 0 {
        ps[0].push(a);
        return;
    }
    let la = *ps[0].peek().unwrap();
    if ps[1].len() == 0 {
        if a < la {
            ps[1].push(-la);
            ps[0].clear();
            ps[0].push(a);
        } else {
            ps[1].push(-a);
        }
        return;
    }
    let ra = -*ps[1].peek().unwrap();
    if a < ra {
        insert(ps, offsets, a, 0);
        let la = *ps[0].peek().unwrap();
        if ps[0].len() == ps[1].len() + 2 {
            ps[0].pop();
            let nla = *ps[0].peek().unwrap();
            offsets[0] -= (la - nla).abs() * ps[0].len() as i64;
            insert(ps, offsets, la, 1);
        }
    } else {
        insert(ps, offsets, a, 1);
        let ra = -*ps[1].peek().unwrap();
        if ps[0].len() < ps[1].len() {
            ps[1].pop();
            let nra = -ps[1].peek().unwrap();
            offsets[1] -= (ra - nra).abs() * ps[1].len() as i64;
            insert(ps, offsets, ra, 0);
        }
    }
}

fn main() {
    let q = read::<usize>();
    let mut query = vec![(0, 0, 0); q];
    for i in 0..q {
        query[i].0 = read::<usize>();
        if query[i].0 == 1 {
            query[i].1 = read::<i64>();
            query[i].2 = read::<i64>();
        }
    }
    solve(&query);
}

fn solve(query: &Vec<(usize, i64, i64)>) -> String {
    let mut ret = "".to_string();
    let q = query.len();
    let mut cnt = 0;
    let mut b_sum = 0;
    let mut ps = vec![BinaryHeap::<i64>::new(); 2];
    let mut offsets = vec![0; 2];
    for i in 0..q {
        let t = query[i].0;
        if t == 1 {
            let a = query[i].1;
            let b = query[i].2;
            b_sum += b;
            push(&mut ps, &mut offsets, a);
            cnt += 1;
        } else {
            let lpos = if cnt == 0 { 0 } else { *ps[0].peek().unwrap() };
            let rpos = if cnt <= 1 {
                lpos
            } else {
                -*ps[1].peek().unwrap()
            };
            let ans = offsets[0] + offsets[1] + cnt / 2 * (rpos - lpos).abs() + b_sum;
            println!("{} {}", lpos, ans);
            // ret += &format!("{} {}\n", lpos, ans);
        }
    }
    return ret;
}

fn naive(query: &Vec<(usize, i64, i64)>) -> String {
    let q = query.len();
    let mut ret = "".to_string();
    let mut b_sum = 0;
    let mut poss = vec![];
    for i in 0..q {
        if query[i].0 == 1 {
            poss.push(query[i].1);
            b_sum += query[i].2;
        } else {
            poss.sort();
            let mut ans = 1i64 << 60;
            let mut pos = poss[0];
            for &p1 in poss.iter() {
                let mut sum = b_sum;
                for &p2 in poss.iter() {
                    sum += (p1 - p2).abs();
                }
                if sum < ans {
                    ans = sum;
                    pos = p1;
                }
            }
            // println!("{} {}", pos, ans);
            ret += &format!("{} {}\n", pos, ans);
        }
    }
    return ret;
}

#[allow(dead_code)]
struct XorShift {
    x: u32,
    y: u32,
    z: u32,
    w: u32,
}
#[allow(dead_code)]
impl XorShift {
    fn new() -> XorShift {
        XorShift {
            x: 0x34fb2383,
            y: 0x327328fa,
            z: 0xabd4b54a,
            w: 0xa9dba8d1,
        }
    }
    fn seed(s: u32) -> XorShift {
        let mut rnd = XorShift::new();
        rnd.w = s;
        rnd
    }
    fn xor128(&mut self) -> u32 {
        let t = self.x ^ (self.x << 11);
        self.x = self.y;
        self.y = self.z;
        self.z = self.w;
        self.w = (self.w ^ (self.w >> 19)) ^ (t ^ (t >> 8));
        self.w
    }
    fn next_i32(&mut self, r: i32) -> i32 {
        (self.xor128() % r as u32) as i32
    }
    fn next_i32_lr(&mut self, l: i32, r: i32) -> i32 {
        self.next_i32(r - l + 1) + l
    }
    fn next_i64(&mut self, r: i64) -> i64 {
        ((((self.xor128() as u64) << 32) + self.xor128() as u64) % r as u64) as i64
    }
    fn next_i64_lr(&mut self, l: i64, r: i64) -> i64 {
        self.next_i64(r - l + 1) + l
    }
    fn next_usize_lr(&mut self, l: usize, r: usize) -> usize {
        self.next_i64_lr(l as i64, r as i64) as usize
    }
    fn next_f64(&mut self, r: f64) -> f64 {
        (self.xor128() as f64) / (0xffffffffu32 as f64) * r
    }
    fn next_f64_lr(&mut self, l: f64, r: f64) -> f64 {
        self.next_f64(r - l) + l
    }
}

#[test]
fn test() {
    let mut rnd = XorShift::new();
    for _iter in 0..100 {
        let q = rnd.next_usize_lr(4, 8);
        let mut query = vec![(0, 0, 0); q];
        for i in 0..q {
            if i % 2 == 0 {
                query[i].0 = 1;
                query[i].1 = rnd.next_i64_lr(0, 4);
                query[i].2 = 0;
            } else {
                query[i] = (2, 0, 0);
            }
        }
        let ret1 = solve(&query);
        let ret2 = naive(&query);
        if ret1 != ret2 {
            println!("{}", q);
            for i in 0..q {
                if query[i].0 == 1 {
                    println!("{} {} {}", query[i].0, query[i].1, query[i].2);
                } else {
                    println!("{}", query[i].0);
                }
            }
            println!("");
            println!("{}", ret1);
            println!("");
            println!("{}", ret2);
            assert!(false);
        }
    }
}


Measured memory_bytes: 14844