Problem:
Score : 400 points

Problem Statement

We have a pyramid with N steps, built with blocks.
The steps are numbered 1 through N from top to bottom.
For each 1≤i≤N, step i consists of 2i-1 blocks aligned horizontally.
The pyramid is built so that the blocks at the centers of the steps are aligned vertically.

A pyramid with N=4 steps

Snuke wrote a permutation of (1, 2, ..., 2N-1) into the blocks of step N.
Then, he wrote integers into all remaining blocks, under the following rule:

The integer written into a block b must be equal to the median of the three integers written into the three blocks directly under b, or to the lower left or lower right of b.

Writing integers into the blocks

Afterwards, he erased all integers written into the blocks.
Now, he only remembers that the integer written into the block of step 1 was x.

Construct a permutation of (1, 2, ..., 2N-1) that could have been written into the blocks of step N, or declare that Snuke's memory is incorrect and such a permutation does not exist.

Constraints

2≤N≤10^5

1≤x≤2N-1

Input

The input is given from Standard Input in the following format:

N x

Output

If no permutation of (1, 2, ..., 2N-1) could have been written into the blocks of step N, print No.

Otherwise, print Yes in the first line, then print 2N-1 lines in addition.

The i-th of these 2N-1 lines should contain the i-th element of a possible permutation.

Sample Input 1

4 4

Sample Output 1

Yes
1
6
3
7
4
5
2

This case corresponds to the figure in the problem statement.

Sample Input 2

2 1

Sample Output 2

No

No matter what permutation was written into the blocks of step N, the integer written into the block of step 1 would be 2.

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

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

class Program{

    const long MOD = (long)1e9 + 7;

    static void Main(string[] args)
    {
        // main ↓
        int[] Nx = ScanIntArray(2);
        int N = Nx[0];
        int x = Nx[1];
        if(N == 2)
        {
            if(x == 2)
            {
                Console.WriteLine("Yes");
                Console.WriteLine("1");
                Console.WriteLine("2");
                Console.WriteLine("3");
            }
            else
            {
                Console.WriteLine("No");
            }
        }
        else // N >= 3 ( 5~ )
        {
            if (x == 1 || x == 2 * N - 1)
            {
                Console.WriteLine("No");
            }
            else
            {
                Console.WriteLine("Yes");
                List<int> res = new List<int>();
                for (int i = 1; i < 2 * N; i++)
                {
                    res.Add(i);
                }
                if(x == 2 * N - 2)
                {
                    res.Remove(x);
                    res.Remove(x - 1);
                    res.Remove(x + 1);
                    res.Remove(x - 2);
                    res.Insert(N - 3, x - 2);
                    res.Insert(N - 3, x + 1);
                    res.Insert(N - 3, x);
                    res.Insert(N - 3, x - 1);
                }
                else
                {
                    res.Remove(x);
                    res.Remove(x - 1);
                    res.Remove(x + 1);
                    res.Remove(x + 2);
                    res.Insert(N - 3, x + 1);
                    res.Insert(N - 3, x);
                    res.Insert(N - 3, x - 1);
                    res.Insert(N - 3, x + 2);
                }
                for (int i = 0; i < 2*N-1; i++)
                {
                    Console.WriteLine(res[i]);
                }
            }
        }
        


        // main↑
    }


    static int Nibutan(long[] array, long k)
    {
        int low = 0 ;
        int high = array.Length-1;
        int mid = high;

        while (low < high)
        {
            mid = (low + high) / 2;
            if(array[mid] >= k) // k以上の最小index.ココを変えるだけ
            {
                high = mid;
            }
            else
            {
                low = mid + 1;
            }
            mid = (low + high) / 2;
        }
        return mid;
    }   

    static int ScanOneInt()
    {
        return int.Parse(Console.ReadLine());
    }

    static long ScanOneLong()
    {
        return long.Parse(Console.ReadLine());
    }

    static string[] ScanStringArray(int lines)
    {
        string[] str = new string[lines];
        for (int i = 0; i < lines; i++)
        {
            str[i] = Console.ReadLine();
        }
        return str;
    }

    static int[] ScanIntArray(int t)
    {
        string[] str = Console.ReadLine().Split(' ');
        int[] ar = new int[t];
        for (int i = 0; i < t; i++)
        {
            ar[i] = int.Parse(str[i]);
        }
        return ar;
    }

    static string[] ScanStringArrayInOneLine(int t)
    {
        string[] str = Console.ReadLine().Split(' ');
        return str;
    }

    static Tuple<int,int> ScanTuple()
    {
        int[] tmp = ScanIntArray(2);
        return new Tuple<int, int>(tmp[0], tmp[1] * -1);
    }

    static long[] ScanLongArray(int t)
    {
        string[] str = Console.ReadLine().Split(' ');
        long[] ar = new long[t];
        for (int i = 0; i < t; i++)
        {
            ar[i] = long.Parse(str[i]);
        }
        return ar;
    }

    static double[] ScanDoubleArray(int t)
    {
        string[] str = Console.ReadLine().Split(' ');
        double[] ar = new double[t];
        for (int i = 0; i < t; i++)
        {
            ar[i] = double.Parse(str[i]);
        }
        return ar;
    }

    static int[,] ScanIntSquareArray(int h, int w)
    {
        int[,] resAr = new int[h, w];
        for (int i = 0; i < h; i++)
        {
            int[] ar = ScanIntArray(w);
            for (int j = 0; j < w; j++)
            {
                resAr[i, j] = ar[j];
            }
        }
        return resAr;
    }

    public static int[,] CombModMake()
    {
        int[,] res = new int[2005, 2005];
        for (int i = 0; i < 2005; i++)
        {
            for (int j = 0; j < 2005; j++)
            {
                if (i == 0 || i < j)
                {
                    res[i, j] = 0;
                }
                else if (j == 0 || i == j)
                {
                    res[i, j] = 1;
                }
                else
                {
                    res[i, j] = (res[i - 1, j] + res[i - 1, j - 1]) % (int)MOD;
                }
            }
        }
        return res;
    }

    // int, long両方で出来るGCDを作った
    public static T GCD<T>(T a, T b)
    {
        if((dynamic)b == 0)
        {
            return a;
        }
        else
        {
            return GCD((dynamic)b, (dynamic)a % (dynamic)b);
        }
    }

    public static bool isPrime(int a) //O(sqrt N)
    {
        int max = (int)Math.Sqrt(a);
        if (a == 1) return false;
        for (int i = 2; i <= max; i++)
        {
            if(a % i == 0)
            {
                return false;
            }
        }
        return true;
    }

}

public class SegmentTree<Monoid>
{
    private bool debug = false;
    // 0-indexed SegmentTree
    public int size;
    Monoid[] segTree;
    Monoid unit;
    public SegmentTree(int inSize, Monoid unit)
    {
        this.unit = unit;
        size = 2;
        while (size < inSize) size *= 2;
        segTree = new Monoid[2 * size];
        for (int i = 0; i < segTree.Length; i++)
        {
            segTree[i] = unit;
            // 単位元なので全部に代入しておけばよい
        }
    }

    public int BinarySearch(int x)
    {
        int high = size;
        int low = 0;
        int mid = (high + low) / 2;
        while (low < high)
        {
            // Console.WriteLine(low + " " + high);
            Monoid cmp = NonRecursiveQuery(0, mid);
            // Console.WriteLine("[ 0, " + mid + " ] -> " + cmp);
            if ((dynamic)cmp >= x)
            {
                high = mid;
            }
            else if ((dynamic)cmp < x)
            {
                low = mid + 1;
            }
            mid = (high + low) / 2;
        }
        return mid;
    }

    public void set(int iter, Monoid val)
    {
        segTree[iter + size - 1] = val;
    }

    public Monoid GetMonoid(int index)
    {
        return segTree[index + size - 1];
    }

    public void add(int iter, Monoid val)
    {
        update(iter, (dynamic)segTree[iter + size - 1] + (dynamic)val);
    }

    public void build()
    {
        // 2段目より上の構築
        for (int k = size - 2; k >= 0; k--)
        {
            segTree[k] = F(segTree[2 * k + 1], segTree[2 * k + 2]);
        }
    }

    public Monoid F(Monoid m1, Monoid m2)
    {
        Monoid res = Program.GCD(m1, m2);
        return res;
    }

    public Monoid Query(int ql, int qr, int index, int nl, int nr)
    {
        // Recursive
        // [ql, qr)について考える
        // index に対応する範囲 nl <= x <= nr
        if (nr <= ql || qr <= nl)
        {
            if (debug) Console.WriteLine("Out: [l , r), [" + nl + " ," + nr + "), " + "index: " + index + " ,unit:" + unit);
            return unit;
        }
        if (ql <= nl && nr <= qr)
        {
            if (debug) Console.WriteLine("All in [l , r): [" + nl + " ," + nr + "), " + "index: " + index + ",rangeAns:" + segTree[index]);
            return segTree[index];
        }
        else
        {
            Monoid vl = Query(ql, qr, index * 2 + 1, nl, (nl + nr) / 2);
            Monoid vr = Query(ql, qr, index * 2 + 2, (nl + nr) / 2, nr);
            if (debug) Console.WriteLine("Recursive: [l , r),+: [" + nl + ", " + nr + "), index->" + index);
            if (debug) Console.WriteLine("(vl, vr): (" + vl + ", " + vr + ")");
            return F(vl, vr);
        }
    }

    public Monoid NonRecursiveQuery(int l, int r)
    {
        // 区間　-> [ l , r ]
        // 非再帰
        int L = l + size - 1;
        int R = r + size - 1;
        Monoid s = unit;
        while (L <= R)
        {
            if (L % 2 == 0)
            {
                s = F(s, segTree[L]);
                L++;
            }
            if (R % 2 == 1)
            {
                s = F(s, segTree[R]);
            }
            L /= 2;
            R /= 2;
            R--;
        }
        return s;
    }

    public void update(int k, Monoid x)
    {
        k += size - 1;
        segTree[k] = x;
        while (true)
        {
            k = (k - 1) / 2;
            segTree[k] = F(segTree[k * 2 + 1], segTree[k * 2 + 2]);
            if (k == 0)
            {
                break;
            }
        }
    }

    public void print()
    {
        Console.Write("Print:");
        for (int i = 0; i < segTree.Length; i++)
        {
            Console.Write(segTree[i] + " ");
        }
        Console.WriteLine("");
    }

}

public class Pair<T,U>: IComparable where T : IComparable<T> where U: IComparable<U>
{
    public T Item1;
    public U Item2;

    public int  CompareTo(object obj)
    {
        Pair<T,U> pair = (Pair<T, U>)obj;
        return Item1.CompareTo(pair.Item1);
    }
    public Pair(T t, U u)
    {
        Item1 = t;
        Item2 = u;
    }

}

// 計算量: Push -> O(logN), Peek -> O(1)。Clear() -> O(logN)
// ToArray()で配列化
public class PriorityQueue<T> where T : IComparable
{
    private IComparer<T> _comparer = null;
    private int _type = 0;
    private T[] _heap;
    private int _sz = 0;
    private int _count = 0;

    /// <summary>
    /// Priority Queue with custom comparer
    /// </summary>
    public PriorityQueue(int maxSize, IComparer<T> comparer)
    {
        _heap = new T[maxSize];
        _comparer = comparer;
    }

    /*
     -> Item: _heap(ヒープを持つ.sizeはmaxSize)
     -> Item: _type -> 0:asc(昇順), 1:desc(降順)
     */
    public PriorityQueue(int maxSize, int type = 0)
    {
        _heap = new T[maxSize];
        _type = type;
    }

    private int Compare(T x, T y)
    {
        if (_comparer != null) return _comparer.Compare(x, y);
        return _type == 0 ? x.CompareTo(y) : y.CompareTo(x);
        // typeが0なら昇順, 1なら降順にソートするCompare
    }

    public void Push(T x)
    {
        _count++;

        //node number
        var i = _sz++;

        while (i > 0)
        {
            //parent node number
            var p = (i - 1) / 2;
            if (Compare(_heap[p], x) <= 0) break;
            _heap[i] = _heap[p];
            i = p;
        }

        _heap[i] = x;
    }

    public T Pop()
    {
        _count--;

        T ret = _heap[0];
        T x = _heap[--_sz];

        int i = 0;
        while (i * 2 + 1 < _sz)
        {
            //children
            int a = i * 2 + 1;
            int b = i * 2 + 2;

            if (b < _sz && Compare(_heap[b], _heap[a]) < 0) a = b;

            if (Compare(_heap[a], x) >= 0) break;

            _heap[i] = _heap[a];
            i = a;
        }

        _heap[i] = x;

        return ret;
    }

    public int Count()  // O(1)
    {
        return _count;
    }

    public T Peek() // O(1)
    {
        return _heap[0];
    }

    public bool Contains(T x)   // O(N)なので注意
    {
        for (int i = 0; i < _sz; i++) if (x.Equals(_heap[i])) return true;
        return false;
    }

    public void Clear()
    {
        while (Count() > 0) Pop();
    }

    public IEnumerator<T> GetEnumerator() // なにこれ
    {
        var ret = new List<T>();

        while (Count() > 0)
        {
            ret.Add(Pop());
        }

        foreach (var r in ret)
        {
            Push(r);
            yield return r;
        }
    }

    public T[] ToArray()
    {
        T[] array = new T[_sz];
        int i = 0;

        foreach (var r in this)
        {
            array[i++] = r;
        }

        return array;
    }
}