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.Globalization;
using System.IO;
using System.Linq;

partial class Solver
{
    class Query
    {
        public int Index;
        public int Type;
        public int A, B;
    }

    struct Data
    {
        public int Index, Value;
    }

    public void Run()
    {
        var Q = ni();

        var queries = new List<Query>();
        var dataA = new List<Data>();
        long currentBSum = 0;
        for (int _ = 0; _ < Q; _++)
        {
            var t = ni();
            if (t == 1)
            {
                var a = ni();
                var b = ni();
                currentBSum += b;
                queries.Add(new Query { Index = _, Type = t, A = a, B = b });
                dataA.Add(new Data { Index = _, Value = a });
            }
            else if (t == 2)
            {
                queries.Add(new Query { Index = _, Type = t });
            }
        }
        dataA.Sort((d1, d2) => d1.Value.CompareTo(d2.Value));
        var positionFromQueryIndex = dataA
            .Select((d, i) => new { Index = i, QueryIndex = d.Index })
            .ToDictionary(g => g.QueryIndex, g => g.Index);

        var ans = new List<string>();

        queries.Reverse();

        var bit = new BinaryIndexTree(dataA.Count + 2);
        var flg = new BinaryIndexTree(dataA.Count + 2);
        for (int i = 0; i < dataA.Count; i++)
        {
            bit.Add(i, dataA[i].Value);
            flg.Add(i, 1);
        }

        int elements = dataA.Count;

        foreach (var q in queries)
        {
            if (q.Type == 1)
            {
                var pos = positionFromQueryIndex[q.Index];
                var current = bit.Sum(pos, pos);
                if (current != q.A) throw new Exception();
                bit.Add(pos, -current);
                flg.Add(pos, -flg.Sum(pos, pos));

                currentBSum -= q.B;

                elements--;
            }
            else
            {
                var medianIndex = (elements - 1) / 2;

                int pos = -1;
                for (int d = (1 << 18); d > 0; d >>= 1)
                {
                    if (pos + d - 1 >= dataA.Count) continue;
                    var newSum = flg.Sum(0, pos + d - 1);

                    if (newSum <= medianIndex)
                    {
                        pos += d;
                    }
                }
                //cout.WriteLine("! " + pos + " " + medianIndex);

                long x = dataA[pos].Value;
                var leftSum = bit.Sum(0, pos - 1);
                var leftNum = medianIndex;
                long f = currentBSum;
                if (leftNum > 0)
                {
                    f += leftNum * x - leftSum;
                }

                var rightSum = bit.Sum(pos + 1, dataA.Count);
                var rightNum = Math.Max(0, elements - 1 - leftNum);

                if (rightNum > 0)
                {
                    f += rightSum - rightNum * x;
                }

                ans.Add(string.Format("{0} {1}", x, f));
            }
        }
        ans.Reverse();
        foreach (var s in ans)
        {
            cout.WriteLine(s);
        }
    }
}

public class BinaryIndexTree
{
    private long[] array;
    public BinaryIndexTree(int size)
    {
        array = new long[size];
    }
    public long Sum(long a, long b)
    { // [a,b]
        if (a != 0) return Sum(0, b) - Sum(0, a - 1);
        long val = 0;
        for (; b >= 0; b = (b & (b + 1)) - 1) val += array[b];
        return val;
    }

    public void Add(int k, long val)
    {
        for (; k < array.Length; k |= k + 1)
            array[k] += val;
    }
}

// PREWRITEN CODE BEGINS FROM HERE
partial class Solver : Scanner
{
    public static void Main(string[] args)
    {
        new Solver(Console.In, Console.Out).Run();
    }

    TextReader cin;
    TextWriter cout;

    public Solver(TextReader reader, TextWriter writer)
        : base(reader)
    {
        this.cin = reader;
        this.cout = writer;
    }
    public Solver(string input, TextWriter writer)
        : this(new StringReader(input), writer)
    {
    }

    public int ni() { return NextInt(); }
    public int[] ni(int n) { return NextIntArray(n); }
    public long nl() { return NextLong(); }
    public long[] nl(int n) { return NextLongArray(n); }
    public double nd() { return NextDouble(); }
    public string ns() { return Next(); }
}

public class Scanner
{
    private TextReader Reader;
    private Queue<String> TokenQueue = new Queue<string>();
    private CultureInfo ci = CultureInfo.InvariantCulture;

    public Scanner()
        : this(Console.In)
    {
    }

    public Scanner(TextReader reader)
    {
        this.Reader = reader;
    }

    public int NextInt() { return Int32.Parse(Next(), ci); }
    public long NextLong() { return Int64.Parse(Next(), ci); }
    public double NextDouble() { return double.Parse(Next(), ci); }
    public string[] NextArray(int size)
    {
        var array = new string[size];
        for (int i = 0; i < size; i++) array[i] = Next();
        return array;
    }
    public int[] NextIntArray(int size)
    {
        var array = new int[size];
        for (int i = 0; i < size; i++) array[i] = NextInt();
        return array;
    }

    public long[] NextLongArray(int size)
    {
        var array = new long[size];
        for (int i = 0; i < size; i++) array[i] = NextLong();
        return array;
    }

    public String Next()
    {
        if (TokenQueue.Count == 0)
        {
            if (!StockTokens()) throw new InvalidOperationException();
        }
        return TokenQueue.Dequeue();
    }

    public bool HasNext()
    {
        if (TokenQueue.Count > 0)
            return true;
        return StockTokens();
    }

    private bool StockTokens()
    {
        while (true)
        {
            var line = Reader.ReadLine();
            if (line == null) return false;
            var tokens = line.Trim().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            if (tokens.Length == 0) continue;
            foreach (var token in tokens)
                TokenQueue.Enqueue(token);
            return true;
        }
    }
}