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: Wrong Answer)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace ABC140F
{
    class Program
    {
        public static void Solve(Input input)
        {
            var n = input.NextInt();
            int m = (int)Math.Pow(2, n);
            var s = input.NextInt(m);

            var slimes = new PriorityQueue<int>();
            var res = new PriorityQueue<int>();

            for (int i = 0; i < m; i++)
            {
                res.Enqueue(s[i]);
            }

            slimes.Enqueue(res.Dequeue());

            for (int i = 0; i < n; i++)
            {
                var sl = slimes.Dequeue();
                for (int j = i; j < n; j++)
                {
                    var r = res.Dequeue();
                    if (r >= sl)
                    {
                        Console.WriteLine("No");
                        return;
                    }

                    slimes.Enqueue(r);
                }
            }

            Console.WriteLine("Yes");
        }

        /// <summary>
        /// 優先度付きキュー(二分ヒープ)
        /// デフォルトは降順ソート
        /// </summary>
        class PriorityQueue<T>
        {
            static readonly int DefaultCapacity = 8;
            readonly List<T> Heap;
            readonly Comparison<T> Comparer;

            public PriorityQueue(int capacity, Comparison<T> comparer)
            {
                Heap = new List<T>(capacity);
                Comparer = comparer;
            }

            public PriorityQueue() : this(DefaultCapacity) { }
            public PriorityQueue(int capacity) : this(capacity, Comparer<T>.Default.Compare) { }
            public PriorityQueue(Comparison<T> comparer) : this(DefaultCapacity, comparer) { }

            /// <summary> 要素追加 </summary>
            public void Enqueue(T item)
            {
                var n = Heap.Count();
                Heap.Add(item);

                while (n > 0)
                {
                    var parent = (n - 1) / 2;
                    if (Comparer(Heap[parent], item) > 0) break;

                    Heap[n] = Heap[parent];
                    n = parent;
                }

                Heap[n] = item;
            }

            /// <summary> 要素追加 </summary>
            public void Push(T item) => Enqueue(item);

            /// <summary> 先頭の値を取得し削除する </summary>
            public T Dequeue()
            {
                if (!Heap.Any())
                {
                    throw new Exception();
                }
                var item = Heap[0];
                var last = Heap.Last();

                var n = Heap.Count() - 1;
                var parent = 0;
                var child = 2 * parent + 1;
                while (child < n)
                {
                    if (child + 1 < n && Comparer(Heap[child + 1], Heap[child]) > 0)
                    {
                        child++;
                    }

                    if (Comparer(last, Heap[child]) > 0) break;

                    Heap[parent] = Heap[child];
                    parent = child;
                    child = 2 * parent + 1;
                }

                Heap[parent] = last;
                Heap.RemoveAt(n);

                return item;
            }

            /// <summary> 先頭の値を取得し削除する </summary>
            public T Pop() => Dequeue();

            /// <summary>
            /// 先頭の値取得（削除はしない）
            /// </summary>
            public T Peek()
            {
                if (!this.Heap.Any()) throw new Exception();

                return this.Heap[0];
            }

            /// <summary>
            /// ヒープに格納されているアイテム数
            /// </summary>
            public int Count() => this.Heap.Count();

            /// <summary>
            /// 一つでも値が格納されているか
            /// </summary>
            public bool Any() => this.Heap.Any();
        }

        #region Main
        public static void Main(string[] args)
        {
            // 出力が少ないときはこれをセットする方が時間かかるけれど
            // そのときにTLEするのはアルゴリズムが悪いせいだし、まあ良しとする
            var needsFlushOutput = true;
            if (needsFlushOutput)
            {
                // 細かく出力しないようにする
                var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
                Console.SetOut(sw);
            }

            // 通常は引数無しで、ファイルから読み出したい場合はpath指定する
            var input = new Input();

            // 仮想的に標準入力をセットする
            // テスト入力したまま提出することがままあるので……
#if DEBUG
            //input.SetText("3 1000000000 999999999 8 7 7 7 5 6");
            //input.SetText("3 10 9 8 7 7 7 7 7");
            //input.SetText("18");
            //input.SetText(string.Join(" ", Enumerable.Range(1, (int)Math.Pow(2, 18))));

#endif

            Solve(input);

            Console.Out.Flush();
        }
        #endregion

        #region Competitive Template
#pragma warning disable CS0414
        static readonly int MOD = (int)1e9 + 7;
        static readonly int[] dx = { 1, 0, -1, 0 };
        static readonly int[] dy = { 0, 1, 0, -1 };
        /// <summary> 左上が原点 </summary>
        static readonly char[] dir = { 'R', 'U', 'L', 'D' };
#pragma warning restore CS0414

        public class Input
        {
            // 変な改行コードがたまに混じっているので、一応セパレート指定する
            // スペース単独指定の方がもちろん早い
            static readonly char[] separator = { ' ', '\r', '\n' };
            readonly StreamReader sr;
            readonly Queue<string> queue;

            /// <summary>
            /// 特定のファイルから読み出したい場合はpath指定する
            /// </summary>
            public Input(string path = "")
            {
                queue = new Queue<string>();

                if (string.IsNullOrEmpty(path)) { sr = new StreamReader(Console.OpenStandardInput()); }
                else { sr = new StreamReader(path); }
            }

            /// <summary>
            /// 入力予約
            /// </summary>
            public void SetText(IEnumerable<string> items)
            {
                foreach (var item in items)
                    SetText(item);
            }

            /// <summary>
            /// 入力予約
            /// </summary>
            public bool SetText(string s)
            {
                if (string.IsNullOrEmpty(s)) return false;

                foreach (var elem in s.Trim().Split(separator, StringSplitOptions.RemoveEmptyEntries))
                    queue.Enqueue(elem);

                return true;
            }

            /// <summary>
            /// 要素が存在するか
            /// </summary>
            public bool Any() => queue.Any() || Read();

            /// <summary>
            /// 内部queueに入力からの値をsplitして格納する
            /// </summary>
            bool Read()
            {
                if (!SetText(sr.ReadLine())) return false;

                if (!queue.Any()) return Read();

                return queue.Any();
            }

            /// <summary>
            /// 次のstringを一つ読み込む
            /// </summary>
            public string Next()
            {
                if (!queue.Any() && !Read()) return "";

                return queue.Dequeue();
            }

            /// <summary>
            /// 指定個数queueにたまるまでenqueueし続ける
            /// </summary>
            bool Accumulate(long n)
            {
                while (queue.Count() < n)
                    if (!Read()) return false;

                return true;
            }

            public int NextInt() => int.Parse(Next());
            public long NextLong() => long.Parse(Next());
            public double NextDouble() => double.Parse(Next());

            /// <summary>
            /// n個の要素をparseして、それぞれにoffsetをaddした配列を返す
            /// </summary>
            T[] NextT<T>(long n, T offset, Func<string, T> parse, Func<T, T, T> add)
            {
                if (!Accumulate(n)) return null;

                var a = new T[n];

                for (int i = 0; i < n; i++)
                    a[i] = add(parse(queue.Dequeue()), offset);

                return a;
            }

            public string[] Next(int n) => NextT(n, "", x => x, (x, y) => x);
            public int[] NextInt(long n, int offset = 0) => NextT(n, offset, int.Parse, (x, y) => x + y);
            public long[] NextLong(int n, long offset = 0) => NextT(n, offset, long.Parse, (x, y) => x + y);
            public double[] NextDouble(int n, double offset = 0.0) => NextT(n, offset, double.Parse, (x, y) => x + y);
        }

        static class Utils
        {
            public static T Max<T>(params T[] objs) => objs.Max();
            public static T Min<T>(params T[] objs) => objs.Min();

            /// <summary>
            /// vでfillされたT[d1][d2]配列を作成する
            /// </summary>
            public static T[][] Create2DArray<T>(int d1, int d2, T v)
            {
                return
                    Enumerable.Repeat(0, d1).Select(_ =>
                    Enumerable.Repeat(v, d2).ToArray()).ToArray();
            }

            /// <summary>
            /// vでfillされたT[d1][d2][d3]配列を作成する
            /// </summary>
            public static T[][][] Create3DArray<T>(int d1, int d2, int d3, T v)
            {
                return
                    Enumerable.Repeat(0, d1).Select(_ =>
                    Enumerable.Repeat(0, d2).Select(__ =>
                    Enumerable.Repeat(v, d3).ToArray()).ToArray()).ToArray();
            }
        }
        #endregion
    }
}