Problem:
Score : 600 points

Problem Statement

We have one slime.

You can set the health of this slime to any integer value of your choice.

A slime reproduces every second by spawning another slime that has strictly less health. You can freely choose the health of each new slime. The first reproduction of our slime will happen in one second.

Determine if it is possible to set the healths of our first slime and the subsequent slimes spawn so that the multiset of the healths of the 2^N slimes that will exist in N seconds equals a multiset S.

Here S is a multiset containing 2^N (possibly duplicated) integers: S_1,~S_2,~...,~S_{2^N}.

Constraints

All values in input are integers.

1 \leq N \leq 18

1 \leq S_i \leq 10^9

Input

Input is given from Standard Input in the following format:

N
S_1 S_2 ... S_{2^N}

Output

If it is possible to set the healths of the first slime and the subsequent slimes spawn so that the multiset of the healths of the 2^N slimes that will exist in N seconds equals S, print Yes; otherwise, print No.

Sample Input 1

2
4 2 3 1

Sample Output 1

Yes

We will show one way to make the multiset of the healths of the slimes that will exist in 2 seconds equal to S.

First, set the health of the first slime to 4.

By letting the first slime spawn a slime whose health is 3, the healths of the slimes that exist in 1 second can be 4,~3.

Then, by letting the first slime spawn a slime whose health is 2, and letting the second slime spawn a slime whose health is 1, the healths of the slimes that exist in 2 seconds can be 4,~3,~2,~1, which is equal to S as multisets.

Sample Input 2

2
1 2 3 1

Sample Output 2

Yes

S may contain multiple instances of the same integer.

Sample Input 3

1
1 1

Sample Output 3

No

Sample Input 4

5
4 3 5 3 1 2 7 8 7 4 6 3 7 2 3 6 2 7 3 2 6 7 3 4 6 7 3 4 2 5 2 3

Sample Output 4

No

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

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    private int N;
    private int[] S;
    private int L;

    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        S = sc.IntArray();
        L = 1 << N;

        var map = new HashMap<int, int>();

        foreach (int i in S)
        {
            map[i]++;
        }

        var ar = map.ToArray();
        Array.Sort(ar, (a, b) => -a.Key.CompareTo(b.Key));

        var tree = new int[L * 2];

        // まだ使ってない部分木の根
        var q = new PriorityQueue<int>();
        q.Enqueue(1);

        foreach (KeyValuePair<int, int> pair in ar)
        {
            int num = pair.Key;
            int cnt = pair.Value;
            if (q.Count < cnt)
            {
                Console.WriteLine("No");
                return;
            }

            List<int> list = new List<int>();
            for (int i = 0; i < cnt; i++)
            {
                int pos = q.Dequeue();
                while (pos < L)
                {
                    int left = pos * 2;
                    int right = left + 1;
                    tree[left] = num;
                    list.Add(right);
                    pos = left;
                }
            }

            foreach (var i in list)
            {
                q.Enqueue(i);
            }
        }

        //Console.WriteLine(string.Join(" ",tree));
        Console.WriteLine("Yes");
    }

    public static void Main(string[] args)
    {
        new Program().Solve();
    }
}

#region PriorityQueue

/// <summary>
/// 指定した型のインスタンスを最も価値が低い順に取り出すことが可能な可変サイズのコレクションを表します．
/// </summary>
/// <typeparam name="T">優先度付きキュー内の要素の型を指定します．</typeparam>
/// <remarks>内部的にはバイナリヒープによって実装されています．</remarks>
public class PriorityQueue<T>
{
    readonly List<T> heap = new List<T>();
    readonly Comparison<T> cmp;

    /// <summary>
    /// デフォルトの比較子を使用してインスタンスを初期化します．
    /// </summary>
    /// <remarks>この操作は O(1) で実行されます．</remarks>
    public PriorityQueue()
    {
        cmp = Comparer<T>.Default.Compare;
    }

    /// <summary>
    /// デリゲートで表されるような比較関数を使用してインスタンスを初期化します．
    /// </summary>
    /// <param name="comparison"></param>
    /// <remarks>この操作は O(1) で実行されます．</remarks>
    public PriorityQueue(Comparison<T> comparison)
    {
        cmp = comparison;
    }

    /// <summary>
    /// 指定された比較子を使用してインスタンスを初期化します．
    /// </summary>
    /// <param name="comparer"></param>
    /// <remarks>この操作は O(1) で実行されます．</remarks>
    public PriorityQueue(IComparer<T> comparer)
    {
        cmp = comparer.Compare;
    }

    /// <summary>
    /// 優先度付きキューに要素を追加します．
    /// </summary>
    /// <param name="item">優先度付きキューに追加される要素</param>
    /// <remarks>最悪計算量 O(log N) で実行されます．</remarks>
    public void Enqueue(T item)
    {
        var pos = heap.Count;
        heap.Add(item);
        while (pos > 0)
        {
            var par = (pos - 1) / 2;
            if (cmp(heap[par], item) <= 0)
                break;
            heap[pos] = heap[par];
            pos = par;
        }

        heap[pos] = item;
    }

    /// <summary>
    /// 優先度付きキューから最も価値が低い要素を削除し，返します．
    /// </summary>
    /// <returns>優先度付きキューから削除された要素．</returns>
    /// <remarks>最悪計算量 O(log N) で実行されます．</remarks>
    public T Dequeue()
    {
        var ret = heap[0];
        var pos = 0;
        var x = heap[heap.Count - 1];

        while (pos * 2 + 1 < heap.Count - 1)
        {
            var lch = pos * 2 + 1;
            var rch = pos * 2 + 2;
            if (rch < heap.Count - 1 && cmp(heap[rch], heap[lch]) < 0) lch = rch;
            if (cmp(heap[lch], x) >= 0)
                break;
            heap[pos] = heap[lch];
            pos = lch;
        }

        heap[pos] = x;
        heap.RemoveAt(heap.Count - 1);
        return ret;
    }

    /// <summary>
    ///  優先度付きキューに含まれる最も価値が低い要素を削除せずに返します．
    /// </summary>
    /// <returns>優先度付きキューに含まれる最も価値が低い要素．</returns>
    /// <remarks>この操作は O(1) で実行されます．</remarks>
    public T Peek()
    {
        return heap[0];
    }

    /// <summary>
    /// 優先度付きキュー内の要素の数を取得します．
    /// </summary>
    /// <returns>優先度付キュー内にある要素の数</returns>
    /// <remarks>最悪計算量 O(1) で実行されます．</remarks>
    public int Count
    {
        get { return heap.Count; }
    }

    /// <summary>
    /// 優先度付きキュー内に要素が存在するかどうかを O(1) で判定します．
    /// </summary>
    /// <returns>優先度付キュー内にある要素が存在するならば true，そうでなければ　false．</returns>
    /// <remarks>この操作は O(1) で実行されます．</remarks>
    public bool Any()
    {
        return heap.Count > 0;
    }

    /// <summary>
    /// 優先度付きキューに含まれる要素を昇順に並べて返します．
    /// </summary>
    /// <remarks>この操作は計算量 O(N log N)で実行されます．</remarks>
    public T[] Items
    {
        get
        {
            var ret = heap.ToArray();
            Array.Sort(ret, cmp);
            return ret;
        }
    }
}

#endregion

class HashMap<K, V> : Dictionary<K, V>
{
    new public V this[K i]
    {
        get
        {
            V v;
            return TryGetValue(i, out v) ? v : base[i] = default(V);
        }
        set { base[i] = value; }
    }
}

class Scanner
{
    public Scanner()
    {
        _pos = 0;
        _line = new string[0];
    }

    const char Separator = ' ';
    private int _pos;
    private string[] _line;

    #region スペース区切りで取得

    public string Next()
    {
        if (_pos >= _line.Length)
        {
            _line = Console.ReadLine().Split(Separator);
            _pos = 0;
        }

        return _line[_pos++];
    }

    public int NextInt()
    {
        return int.Parse(Next());
    }

    public long NextLong()
    {
        return long.Parse(Next());
    }

    public double NextDouble()
    {
        return double.Parse(Next());
    }

    #endregion

    #region 型変換

    private int[] ToIntArray(string[] array)
    {
        var result = new int[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = int.Parse(array[i]);
        }

        return result;
    }

    private long[] ToLongArray(string[] array)
    {
        var result = new long[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = long.Parse(array[i]);
        }

        return result;
    }

    private double[] ToDoubleArray(string[] array)
    {
        var result = new double[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = double.Parse(array[i]);
        }

        return result;
    }

    #endregion

    #region 配列取得

    public string[] Array()
    {
        if (_pos >= _line.Length)
            _line = Console.ReadLine().Split(Separator);

        _pos = _line.Length;
        return _line;
    }

    public int[] IntArray()
    {
        return ToIntArray(Array());
    }

    public long[] LongArray()
    {
        return ToLongArray(Array());
    }

    public double[] DoubleArray()
    {
        return ToDoubleArray(Array());
    }

    #endregion
}