Problem:
Score : 600 points

Problem Statement

There is a function f(x), which is initially a constant function f(x) = 0.

We will ask you to process Q queries in order. There are two kinds of queries, update queries and evaluation queries, as follows:

An update query 1 a b: Given two integers a and b, let g(x) = f(x) + |x - a| + b and replace f(x) with g(x).

An evaluation query 2: Print x that minimizes f(x), and the minimum value of f(x). If there are multiple such values of x, choose the minimum such value.

We can show that the values to be output in an evaluation query are always integers, so we ask you to print those values as integers without decimal points.

Constraints

All values in input are integers.

1 \leq Q \leq 2 \times 10^5

-10^9 \leq a, b \leq 10^9

The first query is an update query.

Input

Input is given from Standard Input in the following format:

Q
Query_1
:
Query_Q

See Sample Input 1 for an example.

Output

For each evaluation query, print a line containing the response, in the order in which the queries are given.

The response to each evaluation query should be the minimum value of x that minimizes f(x), and the minimum value of f(x), in this order, with space in between.

Sample Input 1

4
1 4 2
2
1 1 -8
2

Sample Output 1

4 2
1 -3

In the first evaluation query, f(x) = |x - 4| + 2, which attains the minimum value of 2 at x = 4.

In the second evaluation query, f(x) = |x - 1| + |x - 4| - 6, which attains the minimum value of -3 when 1 \leq x \leq 4. Among the multiple values of x that minimize f(x), we ask you to print the minimum, that is, 1.

Sample Input 2

4
1 -1000000000 1000000000
1 -1000000000 1000000000
1 -1000000000 1000000000
2

Sample Output 2

-1000000000 3000000000

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
class ChokudaiSpeedRun002 {
    static int __cnt = 0;
#if LOCAL_ENVIRONMENT
    static string __mark = "@@@";
#endif
    static void Main(string[] args) {
#if LOCAL_ENVIRONMENT
        StreamReader __sr = new StreamReader("stdin.txt");
        string __str = __sr.ReadToEnd();
        __sr.Close();
        int __index = __str.IndexOf(__mark, 0);
        while (__index != -1) {
            __index = __str.IndexOf(__mark, __index + __mark.Length);
            __cnt++;
        }
        if (__cnt > 0) {
            Console.Write("Eenter test data no(1-{0})? ", __cnt);
            Console.Out.Flush();
            if (!int.TryParse(Console.ReadLine(), out __cnt)) __cnt = 1;
            Console.WriteLine("Select/Default test data: {0}", __cnt);
        }
        var stdin = new System.IO.StreamReader("stdin.txt");
        Console.SetIn(stdin);
#endif
        SimpleScanner sc = new SimpleScanner(__cnt);
        int Q = sc.NextInt();
        var q1 = new PriorityQueue<long>((a, b) => (int)(b - a));
        var q2 = new PriorityQueue<long>((a, b) => (int)(a - b));
        long s1 = 0, s2 = 0, B = 0;
        for (var n = 0; n < Q; n++) {
            int t = sc.NextInt();
            if (t == 1) {
                long a = sc.NextLong(), b = sc.NextLong();
                B += b;
                if (q1.Empty()) {
                    q1.Enqueue(a);
                    s1 += a;
                    continue;
                }
                long am = q1.Peek();
                if (am < a) {
                    q2.Enqueue(a);
                    s2 += a;
                } else {
                    q1.Enqueue(a);
                    s1 += a;
                }
                if (q1.Count < q2.Count) {
                    while (q1.Count < q2.Count) {
                        long x = q2.Dequeue();
                        q1.Enqueue(x);
                        s1 += x;
                        s2 -= x;
                    }
                } else if (q1.Count > q2.Count + 1) {
                    while (q1.Count > q2.Count + 1) {
                        long x = q1.Dequeue();
                        q2.Enqueue(x);
                        s1 -= x;
                        s2 += x;
                    }
                }
#if LOCAL_ENVIRONMENT
        Console.Error.WriteLine($"s1:{s1}, s2:{s2}, B:{B}");
        Console.Error.WriteLine($"q1:{q1.ToString()}");
        Console.Error.WriteLine($"q2:{q2.ToString()}");
#endif
            } else {
                long a = q1.Peek();
                Console.WriteLine($"{a} {a * ((long)q1.Count - (long)q2.Count) - s1 + s2 + B}");
            }
        }
    } //Main

    class PriorityQueue<T> {
        private readonly List<T> heap;
        private readonly Comparison<T> compare;
        private int size;
        public PriorityQueue() : this(Comparer<T>.Default) { }
        public PriorityQueue(IComparer<T> comparer) : this(16, comparer.Compare) { }
        public PriorityQueue(Comparison<T> comparison) : this(16, comparison) { }
        public PriorityQueue(int capacity, Comparison<T> comparison) {
            this.heap = new List<T>(capacity);
            this.compare = comparison;
        }
        public void Enqueue(T item) {
            this.heap.Add(item);
            var i = size++;
            while (i > 0) {
                var p = (i - 1) >> 1;
                if (compare(this.heap[p], item) <= 0) break;
                this.heap[i] = heap[p];
                i = p;
            }
            this.heap[i] = item;
        }
        public T Dequeue() {
            var ret = this.heap[0];
            var x = this.heap[--size];
            var i = 0;
            while ((i << 1) + 1 < size) {
                var a = (i << 1) + 1;
                var b = (i << 1) + 2;
                if (b < size && compare(heap[b], heap[a]) < 0) a = b;
                if (compare(heap[a], x) >= 0) break;
                heap[i] = heap[a];
                i = a;
            }
            heap[i] = x;
            heap.RemoveAt(size);
            return ret;
        }
        public T Peek() { return heap[0]; }
        public int Count { get { return size; } }
        public bool Empty() { return this.Count < 1; }
        public bool Any() { return size > 0; }
        public override string ToString() { return this.heap.ToArray().ToStringA(); }
    }

    public static int LowerBound<T>(T[] array, int start, int end, T value, IComparer<T> comparer) {
        int low = start, high = end, mid;
        while (low < high) {
            mid = ((high - low) >> 1) + low;
            if (comparer.Compare(array[mid], value) < 0)
                low = mid + 1;
            else
                high = mid;
        }
#if LOCAL_ENVIRONMENT
        Console.Error.WriteLine($"LowerBound(array:{array.ToStringA()}");
        Console.Error.WriteLine($"LowerBound(start:{start}, end:{end}, value:{value.ToString()}) return:{low}");
#endif
        return low;
    }
    public static int LowerBound<T>(T[] array, T value) where T : IComparable {
        return LowerBound(array, 0, array.Length, value, Comparer<T>.Default);
    }

    public class BIT {
        int n;
        int[] data;
        public BIT(int size){
            n = size + 1;
            data = new int[n];
        }
        public void add(int i, int x) {
            while (i < n) {
                data[i] += x;
                i += i & -i;
            }
        }
        public int sum(int i) {
            int ret = 0;
            while (i > 0) {
                ret += data[i];
                i -= i & -i;
            }
            return ret;
        }
    }

    public class Item : IEquatable<Item>, IComparable<Item> {
        public long value { get; set; }
        public long count { get; set; }
        public Item(long count, long value) {
            this.value = value;
            this.count = count;
        }
        public override string ToString() {
            return $"[value:{this.value}, count:{this.count}]";
        }
        public bool Equals(Item other) {
            if (other == null) return false;
            return this.value == other.value && this.count == other.count;
        }
        public override bool Equals(Object obj) {
            if (obj == null) return false;
            Item item = obj as Item;
            if (item == null)  return false;
            else return Equals(item);
        }
        public override int GetHashCode() {
            long hc = this.value * this.count;
            return hc.GetHashCode();
        }
        public int CompareTo(Item other) {
            if (other == null) return -1;
            if (this.value == other.value)
                return this.count.CompareTo(other.count);
            else
                return -1 * this.value.CompareTo(other.value);
        }
        public int Compare(Item x, Item y) {
            if (x == null) return 1;
            else return x.CompareTo(y);

        }
    }

    public class SimpleScanner {
        private int cnt;
        private string[] items;
        public SimpleScanner(int cnt = 0) {
            this.cnt = 0;
            var sb = new StringBuilder();
            var s = Console.ReadLine();
            while (s != null) {
                sb.Append(s + " ");
                s = Console.ReadLine();
            }
            this.items = sb.ToString().Split(' ');
#if LOCAL_ENVIRONMENT
            if (cnt > 0) {
                int index = Array.IndexOf(this.items, __mark + cnt.ToString());
                this.cnt = index + 1;
            }
            Console.Error.WriteLine("SimpleScanner.cnt: {0}", this.cnt);
            Console.Error.WriteLine("SimpleScanner.items: {0}", this.items.ToStringA());
#endif
        }
        public void SetCnt(int n) { this.cnt = n; }
        public int NextInt() {
            return int.Parse(this.items[this.cnt++]);
        }
        public long NextLong() {
            return long.Parse(this.items[this.cnt++]);
        }
        public string NextString() {
            return this.items[this.cnt++];
        }
        public int[] NextIntArray(int n) {
            if (n < 1) throw new IndexOutOfRangeException("引数は1以上であること！");
            var result = new int[n];
            for (var i = 0; i < n; i++) result[i] = this.NextInt();
#if LOCAL_ENVIRONMENT
            Console.Error.WriteLine("{0}", result.ToStringA());
#endif
            return result;
        }
        public long[] NextLongArray(int n) {
            if (n < 1) throw new IndexOutOfRangeException("引数は1以上であること！");
            var result = new long[n];
            for (var i = 0; i < n; i++) result[i] = this.NextLong();
#if LOCAL_ENVIRONMENT
            Console.Error.WriteLine("{0}", result.ToStringA());
#endif
            return result;
        }
        public string[] NextStringArray(int n) {
            if (n < 1) throw new IndexOutOfRangeException("引数は1以上であること！");
            var result = new string[n];
            for (var i = 0; i < n; i++) result[i] = this.NextString();
#if LOCAL_ENVIRONMENT
            Console.Error.WriteLine("{0}", result.ToStringA());
#endif
            return result;
        }
        public int[][] NextInt2Col(int n) {
            const int M = 2;
            if (n < 1) throw new IndexOutOfRangeException("引数は1以上であること！");
            int[][] result = new int[M][] {
                new int[n],
                new int[n],
            };
            for (var i = 0; i < n; i++) {
                result[0][i] = this.NextInt();
                result[1][i] = this.NextInt();
            }
#if LOCAL_ENVIRONMENT
            Console.Error.WriteLine("NextInt2Col: [");
            for (var i = 0; i < M; i++)
                Console.Error.WriteLine("  {0},", result[i].ToStringA());
            Console.Error.WriteLine("]");
#endif
            return result;
        }
    }

}
static class Extensions {
    public static string ToStringA<T>(this T[] array, string separator = ", ", string braces = "[]") {
        string bL = braces.Length > 0 ? braces[0].ToString() : "";
        string bR = braces.Length > 1 ? braces[1].ToString() : "";
        return bL + String.Join(separator, array) + bR;
    }
}