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.Linq;
using System.Collections.Generic;
using static System.Console;
using System.Text;
using System.IO;

namespace AtCoder
{
    class Program
    {
        static public long[] Sarray() { return ReadLine().Split().Select(long.Parse).ToArray(); }
        static public List<long> Slist() { return ReadLine().Split().Select(long.Parse).ToList(); }


        //平行二分探索木
        class BinarySearchTree<T> where T : IComparable<T>
        {
            protected class node
            {
                public node left = null;
                public node right = null;
                public T key = default(T);
                public node parent = null;
                public int height;
                public int count = 1;
            }
            node root = null;
            protected bool change;
            int height(node t) => t?.height ?? 0;
            int bias(node t) => height(t.left) - height(t.right);
            void modHeight(node t) => t.height = 1 + Math.Max(height(t.left), height(t.right));
            //vの左回転
            node rotateL(node v)
            {
                var u = v.right;
                var t2 = u.left;
                u.left = v; u.parent = v.parent; v.parent = u;
                if (u.parent != null)
                    if (u.parent.right == v) u.parent.right = u;
                    else u.parent.left = u;
                else
                    root = u;
                v.right = t2; if (t2 != null) t2.parent = v;
                modHeight(u.left);
                modHeight(u);
                return u;
            }
            //uの右回転
            node rotateR(node u)
            {
                var v = u.left;
                var t2 = v.right;
                v.right = u; v.parent = u.parent; u.parent = v;
                if (v.parent != null)
                    if (v.parent.right == u) v.parent.right = v;
                    else v.parent.left = v;
                else
                    root = v;
                u.left = t2; if (t2 != null) t2.parent = u;
                modHeight(v.right);
                modHeight(v);
                return v;
            }
            //tの二重回転(左→右)
            node rotateLR(node t)
            {
                t.left = rotateL(t.left);
                return rotateR(t);
            }
            //tの二重回転(右→左)
            node rotateRL(node t)
            {
                t.right = rotateR(t.right);
                return rotateL(t);
            }
            //挿入時の修正
            node balanceLi(node t) => balanceL(t);
            node balanceRi(node t) => balanceR(t);
            //削除時の修正
            node balanceLd(node t) => balanceR(t);
            node balanceRd(node t) => balanceL(t);
            //左部分木への挿入/右部分木での削除に伴う修正
            node balanceL(node t)
            {
                if (!change) return t;
                var h = height(t);
                if (bias(t) == 2)
                {
                    if (0 <= bias(t.left))
                        t = rotateR(t);
                    else
                        t = rotateLR(t);
                }
                else modHeight(t);
                change = (h != height(t));
                return t;
            }
            //右部分木への挿入/左部分木での削除に伴う修正
            node balanceR(node t)
            {
                if (!change) return t;
                var h = height(t);
                if (bias(t) == -2)
                {
                    if (bias(t.right) <= 0)
                        t = rotateL(t);
                    else
                        t = rotateRL(t);
                }
                else modHeight(t);
                change = (h != height(t));
                return t;
            }


            public BinarySearchTree() { }

            //挿入
            public void insert(T z)
            {
                change = true;
                _insert(new node() { key = z, height = 1 });
            }
            protected void _insert(node z)
            {
                node y = null;
                node x = root;
                while (x != null)
                {
                    y = x;
                    if (z.key.CompareTo(x.key) == 0)
                    {
                        ++x.count;
                        change = false;
                        return;
                    }
                    if (z.key.CompareTo(x.key) < 0)
                        x = x.left;
                    else
                        x = x.right;
                }
                if (y == null)
                {
                    root = z;
                    change = false;
                }
                else if (z.key.CompareTo(y.key) < 0)
                {
                    y.left = z;
                    y.left.parent = y;
                }
                else
                {
                    y.right = z;
                    y.right.parent = y;
                }
                //挿入に伴う修正
                var s = z;
                while (s.parent != null)
                {
                    if (s.parent.left == s)
                        s = balanceLi(s.parent);
                    else
                        s = balanceRi(s.parent);
                }
            }
            //検索
            public bool find(T v)
            {
                var n = _find(v);
                return n == null ? false : true;
            }
            protected node _find(T v)
            {
                var x = root;
                while (x != null)
                {
                    if (x.key.CompareTo(v) == 0)
                        return x;
                    if (x.key.CompareTo(v) < 0)
                        x = x.right;
                    else
                        x = x.left;
                }
                return null;
            }
            public bool rower_bound(T v, ref T r)
            {
                if (null == root)
                    return false;
                var x = root;
                var f = false;
                while (x != null)
                {
                    if (x.key.CompareTo(v) == 0)
                    {
                        r = x.key;
                        return true;
                    }
                    if (x.key.CompareTo(v) < 0)
                        x = x.right;
                    else
                    {
                        f = true;
                        r = x.key;
                        x = x.left;
                    }
                }
                return f;
            }

            //削除
            public void delete(T v)
            {
                var n = _find(v);
                if (n == null) return;
                --n.count;
                if (n.count <= 0)
                {
                    change = true;
                    _delete(_find(v));
                }
            }
            protected void _delete(node n)
            {
                if (n == null)
                    return;
                if (n == root)
                {
                    change = false;
                    if (n.left == null && n.right == null)
                        root = null;
                    else if (n.left != null && n.right == null)
                    {
                        root = n.left;
                        root.parent = null;
                    }
                    else if (n.left == null && n.right != null)
                    {
                        root = n.right;
                        root.parent = null;
                    }
                    else
                    {
                        var next = n.right;
                        while (next.left != null)
                            next = next.left;
                        n.key = next.key;
                        n.count = next.count;
                        change = true;
                        _delete(next);
                    }
                    return;
                }
                var spl = n.parent.left;
                if (n.left == null && n.right == null)
                {
                    if (n == n.parent.right)
                        n.parent.right = null;
                    else
                        n.parent.left = null;
                }
                else if (n.left != null && n.right == null)
                {
                    n.left.parent = n.parent;
                    if (n == n.parent.right)
                        n.parent.right = n.left;
                    else
                        n.parent.left = n.left;
                }
                else if (n.left == null && n.right != null)
                {
                    n.right.parent = n.parent;
                    if (n == n.parent.right)
                        n.parent.right = n.right;
                    else
                        n.parent.left = n.right;
                }
                else
                {
                    var next = n.right;
                    while (next.left != null)
                        next = next.left;
                    n.key = next.key;
                    n.count = next.count;
                    _delete(next);
                }
                //削除に伴う修正
                var s = n;
                while (s.parent != null)
                {
                    if (spl == s)
                        s = balanceLd(s.parent);
                    else
                        s = balanceRd(s.parent);
                    spl = s.parent?.left;
                }
            }
            public bool max(ref T r)
            {
                r = default(T);
                if (root == null)
                    return false;
                var x = root;
                while (x != null)
                {
                    r = x.key;
                    x = x.right;
                }
                return true;
            }
            public bool min(ref T r)
            {
                r = default(T);
                if (root == null)
                    return false;
                var x = root;
                while (x != null)
                {
                    r = x.key;
                    x = x.left;
                }
                return true;
            }
            //vより一つ前の値を得る
            public bool prev(T v, ref T r)
            {
                var t = _find(v);
                if (null == t)
                    return false;
                if (null != t.left)
                {
                    t = t.left;
                    while (t.right != null)
                        t = t.right;
                    r = t.key;
                    return true;
                }
                while (t.parent != null)
                {
                    if (t.parent.right == t)
                    {
                        r = t.parent.key;
                        return true;
                    }
                    t = t.parent;
                }
                return false;
            }
            //vより一つ後の値を得る
            public bool next(T v, ref T r)
            {
                var t = _find(v);
                if (null == t)
                    return false;
                if (null != t.right)
                {
                    t = t.right;
                    while (t.left != null)
                        t = t.left;
                    r = t.key;
                    return true;
                }
                while (t.parent != null)
                {
                    if (t.parent.left == t)
                    {
                        r = t.parent.key;
                        return true;
                    }
                    t = t.parent;
                }
                return false;
            }
        }
        static void Main(string[] args)
        {
            var N = Sarray()[0];
            var S = Slist();
            S.Sort();
            var T = new BinarySearchTree<long>();
            for (var i = 0; i < S.Count - 1; ++i)
                T.insert(S[i]);
            var V = new List<long>();
            V.Add( S.Last());
            for (var i = 0; i < N; ++i)
            {
                var W = new List<long>(V);
                foreach (var v in V)
                {
                    long t = v;
                    long p = 0;
                    if (!T.rower_bound(v, ref t))
                        T.max(ref p);
                    else if (!T.prev(t, ref p))
                    {
                        WriteLine("No");
                        return;
                    }
                    W.Add(p);
                    T.delete(p);
                }
                W.Sort();
                W.Reverse();
                V = W;
            }
            WriteLine("Yes");
        }
    }
}