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: Time Limit Exceeded)

using System;
using System.Collections.Generic;
using System.Linq;
using IEnumerable = System.Collections.IEnumerable;
using IEnumerator = System.Collections.IEnumerator;
using BitArray = System.Collections.BitArray;
using BigInteger = System.Numerics.BigInteger;
using TextReader = System.IO.TextReader;
using static AtCoderProject.Global;

namespace AtCoderProject
{
    public class Program
    {
        public object Calc()
        {
            var N = consoleReader.Int;
            var s = new List<int>(consoleReader.Split.Int);
            s.Sort();

            var current = new SortedCollection<int>(N, ComparerReverse<int>()) { s[s.Count - 1] };
            s.RemoveAt(s.Count - 1);
            while (s.Count > 0)
            {
                var nexts = new int[current.Count];
                var i = 0;
                foreach (var item in current)
                {
                    var bi = 0;
                    var r = s.Count - 1;
                    while (bi <= r)
                    {
                        var m = (bi + r) / 2;
                        var res = s[m].CompareTo(item);
                        if (res < 0) bi = m + 1;
                        else r = m - 1;
                    }
                    bi--;
                    if (bi < 0) return "No";
                    nexts[i++] = s[bi];
                    s.RemoveAt(bi);
                }
                foreach (var item in nexts)
                    current.Add(item);
            }

            return "Yes";
        }

        [System.Diagnostics.DebuggerDisplay("Count = {Count}")]
        class SortedCollection<T> : IList<T>
        {
            [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)] List<T> list;

            public SortedCollection() : this(Comparer<T>.Default) { }
            public SortedCollection(int capacity) : this(capacity, Comparer<T>.Default) { }
            public SortedCollection(IComparer<T> comparer) { Comparer = comparer; list = new List<T>(); }
            public SortedCollection(int capacity, IComparer<T> comparer) { Comparer = comparer; list = new List<T>(capacity); }

            [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] public IComparer<T> Comparer { get; }
            [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] public bool IsReadOnly => false;
            [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] public int Count => list.Count;

            public T this[int index]
            {
                get { return list[index]; }
                set { list[index] = value; }
            }

            /// <summary>
            /// 与えられた比較関数に従って，<paramref name="item"/> であるような最小のインデックスを取得します．見つからなかった場合は<paramref name="item"/>より大きい最小のインデックスのビット反転を返します.
            /// </summary>
            /// <typeparam name="T"><see cref="IList{T}"/> の要素の型を指定します．</typeparam>
            /// <param name="item">対象となる要素</param>
            /// <returns><paramref name="item"/> が見つかった場合は0-indexed でのインデックス．見つからなかった場合は<paramref name="item"/>より大きい最小のインデックスのビット反転.</returns>
            /// <remarks> 比較関数に対して昇順であることを仮定しています．この関数は O(log N) で実行されます．</remarks>
            public int BinarySearch(T item) => list.BinarySearch(item, Comparer);

            private int BinarySearchImpl(T item, bool isLowerBound)
            {
                var l = 0;
                var r = this.Count - 1;
                while (l <= r)
                {
                    var m = (l + r) / 2;
                    var res = Comparer.Compare(this[m], item);
                    if (res < 0 || (res == 0 && !isLowerBound)) l = m + 1;
                    else r = m - 1;
                }
                return l;
            }

            /// <summary>
            ///　デフォルトの比較関数に従って，<paramref name="a"/> の要素のうち，<paramref name="item"/> 以上の要素であるような最小のインデックスを取得します．
            /// </summary>
            /// <typeparam name="T"><see cref="IList{T}"/> の要素の型を指定します．</typeparam>
            /// <param name="a">対象となるコレクション</param>
            /// <param name="item">対象となる要素</param>
            /// <param name="f"></param>
            /// <returns><paramref name="item"/> 以上の要素であるような最小の o-indexed でのインデックス．</returns>
            /// <remarks> <paramref name="a"/> は比較関数に対して昇順であることを仮定しています．この関数は O(log N) で実行されます．</remarks>
            public int LowerBound(T item) => BinarySearchImpl(item, true);

            /// <summary>
            ///　デフォルトの比較関数に従って，<paramref name="a"/> の要素のうち，<paramref name="v"/> より真に大きい要素が現れる最小のインデックスを取得します．
            /// </summary>
            /// <typeparam name="T"><see cref="IList{T}"/> の要素の型を指定します．</typeparam>
            /// <param name="a">対象となるコレクション</param>
            /// <param name="v">対象となる要素</param>
            /// <param name="f"></param>
            /// <returns><paramref name="v"/> 以上の要素であるような最小の o-indexed でのインデックス．</returns>
            /// <remarks> <paramref name="a"/> は比較関数に対して昇順であることを仮定しています．この関数は O(log N) で実行されます．</remarks>
            public int UpperBound(T item) => BinarySearchImpl(item, false);

            void ICollection<T>.Add(T item) => this.Add(item);
            public int Add(T item)
            {
                var index = BinarySearch(item);
                if (index < 0)
                    index = ~index;
                list.Insert(index, item);
                return index;
            }

            public int IndexOf(T item)
            {
                var index = BinarySearch(item);
                if (index >= 0) return index;
                else return -1;
            }
            public bool Contains(T item) => BinarySearch(item) >= 0;
            public void Clear() => list.Clear();
            public void CopyTo(T[] array, int arrayIndex) => list.CopyTo(array, arrayIndex);

            public bool Remove(T item)
            {
                int index = this.IndexOf(item);
                if (index < 0)
                    return false;
                list.RemoveAt(index);
                return true;
            }

            IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
            public IEnumerator<T> GetEnumerator() => list.GetEnumerator();
            public void Insert(int index, T item) { throw new NotImplementedException(); }
            public void RemoveAt(int index) => list.RemoveAt(index);
        }

        #region いつもの
#pragma warning disable
        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] private ConsoleReader consoleReader;
        public Program(ConsoleReader consoleReader) { this.consoleReader = consoleReader; }
        static void Main() => Console.WriteLine(new Program(new ConsoleReader(Console.In)).Calc()); static string AllLines<T>(IEnumerable<T> source) => string.Join("\n", source);
    }
    static class Global
    {
        private class ComparerReverseImpl<T> : Comparer<T> where T : IComparable<T> { public override int Compare(T y, T x) => x.CompareTo(y); public override bool Equals(object obj) => obj != null && GetType() == obj.GetType(); public override int GetHashCode() => GetType().GetHashCode(); }
        public static IComparer<T> ComparerReverse<T>() where T : IComparable<T> => new ComparerReverseImpl<T>();
        public static BigInteger ParseBigInteger(string s)
        {
            // MonoのBigInteger.Parseが遅いので自前実装
            var res = BigInteger.Zero;
            var splited = new string[(s.Length + 7) / 8];
            for (int i = 0; i < splited.Length - 1; i++)
            {
                splited[i] = s.Substring(8 * i, 8);
            }
            splited[splited.Length - 1] = s.Substring(8 * (splited.Length - 1));
            foreach (var sp in splited)
            {
                res *= (int)Math.Pow(10, sp.Length);
                res += int.Parse(sp);
            }
            return res;
        }
    }
    static class Ext
    {
        public static IComparer<T> Reverse<T>(this IComparer<T> comparer) => Comparer<T>.Create((x, y) => comparer.Compare(y, x));
        public static Dictionary<TKey, int> GroupCount<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) => source.GroupBy(keySelector).ToDictionary(g => g.Key, g => g.Count());
        public static Dictionary<TKey, int> GroupCount<TKey>(this IEnumerable<TKey> source) => source.GroupCount(i => i);
    }
    public class ConsoleReader { private string[] ReadLineSplit() => textReader.ReadLine().Split(Array.Empty<char>(), StringSplitOptions.RemoveEmptyEntries); private string[] line = Array.Empty<string>(); private int linePosition; private TextReader textReader; public ConsoleReader(TextReader tr) { textReader = tr; } public int Int => int.Parse(String); public int Int0 => Int - 1; public long Long => long.Parse(String); public double Double => double.Parse(String); public string String { get { if (linePosition >= line.Length) { linePosition = 0; line = ReadLineSplit(); } return line[linePosition++]; } } public class SplitLine { private string[] splited; public SplitLine(ConsoleReader cr) { splited = cr.ReadLineSplit(); cr.line = Array.Empty<string>(); } public int[] Int => String.Select(x => int.Parse(x)).ToArray(); public int[] Int0 => String.Select(x => int.Parse(x) - 1).ToArray(); public long[] Long => String.Select(x => long.Parse(x)).ToArray(); public double[] Double => String.Select(x => double.Parse(x)).ToArray(); public string[] String => splited; } public SplitLine Split => new SplitLine(this); public class RepeatReader : IEnumerable<ConsoleReader> { ConsoleReader cr; int count; public RepeatReader(ConsoleReader cr, int count) { this.cr = cr; this.count = count; } public IEnumerator<ConsoleReader> GetEnumerator() => Enumerable.Repeat(cr, count).GetEnumerator(); System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); public IEnumerable<string> String => this.Select(cr => cr.String); public IEnumerable<int> Int => this.Select(cr => cr.Int); public IEnumerable<int> Int0 => this.Select(cr => cr.Int - 1); public IEnumerable<long> Long => this.Select(cr => cr.Long); public IEnumerable<double> Double => this.Select(cr => cr.Double); } public RepeatReader Repeat(int count) => new RepeatReader(this, count); }
    #endregion
}