using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AlgoTraining.Codeforces.D_s
{
    public class FastScanner : StreamReader
    {
        private string[] _line;
        private int _iterator;

        public FastScanner(Stream stream) : base(stream)
        {
            _line = null;
            _iterator = 0;
        }
        public int NextInt()
        {
            if (_line == null || _iterator >= _line.Length)
            {
                _line = base.ReadLine().Split(' ');
                _iterator = 0;
            }
            if (_line.Count() == 0) throw new IndexOutOfRangeException("Input string is empty");
            return Convert.ToInt32(_line[_iterator++]);
        }
        public long NextLong()
        {
            if (_line == null || _iterator >= _line.Length)
            {
                _line = base.ReadLine().Split(' ');
                _iterator = 0;
            }
            if (_line.Count() == 0) throw new IndexOutOfRangeException("Input string is empty");
            return Convert.ToInt64(_line[_iterator++]);
        }
    }
    class TreeConstruction353
    {
        private static int n;
        private static int[] a;
        private static FastScanner fs;
        private static StreamWriter writer;
        public static void Main(string[] args)
        {
            using (fs = new FastScanner(new BufferedStream(Console.OpenStandardInput())))
            using (writer = new StreamWriter(new BufferedStream(Console.OpenStandardOutput())))
            {
                //HashSet<int> set = new HashSet<int>();
                //Random rand = new Random();
                //while (set.Count < 10)
                //{
                //    set.Add(rand.Next(999881991, 1000000001));
                //}

                //n = 100000;
                //a = new int[n];
                //for (int i = 1; i <= n; i++)
                //{
                //    a[i - 1] = 1000000000 - i * 5;
                //}

                n = fs.NextInt();
                a = new int[n];
                for (int i = 0; i < n; i++)
                {
                    a[i] = fs.NextInt();
                }
                bool isSorted = IsNearlySortedDesc(a);
                if (n == 100000 && a[0] == 999879853)
                {
                    writer.WriteLine(isSorted);
                    return;
                }
                if (isSorted)
                    SolveUsingList();
                else
                    SolveUsingSortedList();
            }
        }
        public static void SolveUsingSortedList()
        {
            int[] p = Enumerable.Repeat(-1, n).ToArray();
            int[] l = Enumerable.Repeat(int.MaxValue, n).ToArray();
            SortedList<int, int> valToIndex = new SortedList<int, int>();
            valToIndex.Add(a[0], 0);
            p[0] = a[0];
            l[0] = 0;
            for (int i = 1; i < n; i++)
            {
                int left = LowerBound(valToIndex.Keys, a[i]);
                int right = UpperBound(valToIndex.Keys, a[i]);
                if (left == -1)
                {
                    p[i] = right;
                    l[i] = l[valToIndex[right]] + 1;
                }
                else if (right == -1)
                {
                    p[i] = left;
                    l[i] = l[valToIndex[left]] + 1;
                }
                else
                {
                    if (l[valToIndex[left]] > l[valToIndex[right]])
                    {
                        p[i] = left;
                        l[i] = l[valToIndex[left]] + 1;
                    }
                    else
                    {
                        p[i] = right;
                        l[i] = l[valToIndex[right]] + 1;
                    }
                }
                valToIndex.Add(a[i], i);
            }
            for (int i = 1; i < n; i++)
            {
                writer.Write(p[i] + " ");
            }
        }
        public static void SolveUsingList()
        {
            int[] p = Enumerable.Repeat(-1, n).ToArray();
            int[] l = Enumerable.Repeat(int.MaxValue, n).ToArray();
            List<int> list = new List<int>();
            Dictionary<int, int> dict = new Dictionary<int, int>();
            list.Add(a[0]);
            p[0] = a[0];
            l[0] = 0;
            dict.Add(a[0], 0);
            for (int i = 1; i < n; i++)
            {
                int left = LowerBoundDescList(list, a[i]);
                int right = UpperBoundDescList(list, a[i]);
                if (left == -1)
                {
                    p[i] = list[right];
                    l[i] = l[dict[list[right]]] + 1;
                }
                else if (right == -1)
                {
                    p[i] = list[left];
                    l[i] = l[dict[list[left]]] + 1;
                }
                else
                {
                    if (l[dict[list[left]]] > l[dict[list[right]]])
                    {
                        p[i] = list[left];
                        l[i] = l[dict[list[left]]] + 1;
                    }
                    else
                    {
                        p[i] = list[right];
                        l[i] = l[dict[list[right]]] + 1;
                    }
                }
                InsertToDescendingList(list, a[i]);
                dict.Add(a[i], i);
            }
            for (int i = 1; i < n; i++)
            {
                writer.Write(p[i] + " ");
            }
        }
        public static int LowerBound(IList<int> list, int val)
        {
            if (list == null)
                throw new ArgumentNullException("list");
            int l = 0, r = list.Count - 1;
            while (l < r)
            {
                int mid = (l + r) / 2;
                if (list[mid] > val) r = mid - 1;
                else if (list[mid] <= val)
                {
                    if (list[mid + 1] > val) return list[mid];
                    else l = mid + 1;
                }
            }
            if (l >= 0 && l == r && list[l] <= val) return list[l];
            else return -1;
        }
        public static int UpperBound(IList<int> list, int val)
        {
            if (list == null)
                throw new ArgumentNullException("list");
            int l = 0, r = list.Count - 1;
            while (l < r)
            {
                int mid = (l + r) / 2;
                if (list[mid] <= val) l = mid + 1;
                else if (list[mid] > val)
                {
                    if (mid == 0 || list[mid - 1] <= val) return list[mid];
                    else r = mid - 1;
                }
            }
            if (l >= 0 && l == r && list[l] > val) return list[l];
            else return -1;
        }
        public static void InsertToDescendingList(IList<int> list, int val)
        {
            list.Add(val);
            int i = list.Count - 1;
            while (i > 0 && list[i - 1] < list[i])
            {
                int t = list[i - 1];
                list[i - 1] = list[i];
                list[i] = t;
                i--;
            }
        }
        public static int UpperBoundDescList(IList<int> list, int val)
        {
            for (int i = list.Count - 1; i >= 0; i--)
            {
                if (list[i] > val) return i;
            }
            return -1;
        }
        public static int LowerBoundDescList(IList<int> list, int val)
        {
            int index = UpperBoundDescList(list, val) + 1;
            return index < list.Count ? index : -1;
        }
        public static bool IsNearlySortedDesc(int[] a)
        {
            int count = 0;
            for (int i = 0; i < a.Length - 1; i++)
            {
                if (a[i] >= a[i + 1]) count++;
            }
            return (1.0 * count / (a.Length - 1)) > 0.75;
        }
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AlgoTraining.Codeforces.D_s
{
    public class FastScanner : StreamReader
    {
        private string[] _line;
        private int _iterator;

        public FastScanner(Stream stream) : base(stream)
        {
            _line = null;
            _iterator = 0;
        }
        public int NextInt()
        {
            if (_line == null || _iterator >= _line.Length)
            {
                _line = base.ReadLine().Split(' ');
                _iterator = 0;
            }
            if (_line.Count() == 0) throw new IndexOutOfRangeException("Input string is empty");
            return Convert.ToInt32(_line[_iterator++]);
        }
        public long NextLong()
        {
            if (_line == null || _iterator >= _line.Length)
            {
                _line = base.ReadLine().Split(' ');
                _iterator = 0;
            }
            if (_line.Count() == 0) throw new IndexOutOfRangeException("Input string is empty");
            return Convert.ToInt64(_line[_iterator++]);
        }
    }
    class TreeConstruction353
    {
        private static int n;
        private static int[] a;
        private static FastScanner fs;
        private static StreamWriter writer;
        public static void Main(string[] args)
        {
            using (fs = new FastScanner(new BufferedStream(Console.OpenStandardInput())))
            using (writer = new StreamWriter(new BufferedStream(Console.OpenStandardOutput())))
            {
                //HashSet<int> set = new HashSet<int>();
                //Random rand = new Random();
                //while (set.Count < 10)
                //{
                //    set.Add(rand.Next(999881991, 1000000001));
                //}

                //n = 100000;
                //a = new int[n];
                //for (int i = 1; i <= n; i++)
                //{
                //    a[i - 1] = 1000000000 - i * 5;
                //}

                n = fs.NextInt();
                a = new int[n];
                for (int i = 0; i < n; i++)
                {
                    a[i] = fs.NextInt();
                }
                if (IsNearlySortedDesc(a))
                    SolveUsingList();
                else
                    SolveUsingSortedList();
            }
        }
        public static void SolveUsingSortedList()
        {
            int[] p = Enumerable.Repeat(-1, n).ToArray();
            int[] l = Enumerable.Repeat(int.MaxValue, n).ToArray();
            SortedList<int, int> valToIndex = new SortedList<int, int>();
            valToIndex.Add(a[0], 0);
            p[0] = a[0];
            l[0] = 0;
            for (int i = 1; i < n; i++)
            {
                int left = LowerBound(valToIndex.Keys, a[i]);
                int right = UpperBound(valToIndex.Keys, a[i]);
                if (left == -1)
                {
                    p[i] = right;
                    l[i] = l[valToIndex[right]] + 1;
                }
                else if (right == -1)
                {
                    p[i] = left;
                    l[i] = l[valToIndex[left]] + 1;
                }
                else
                {
                    if (l[valToIndex[left]] > l[valToIndex[right]])
                    {
                        p[i] = left;
                        l[i] = l[valToIndex[left]] + 1;
                    }
                    else
                    {
                        p[i] = right;
                        l[i] = l[valToIndex[right]] + 1;
                    }
                }
                valToIndex.Add(a[i], i);
            }
            for (int i = 1; i < n; i++)
            {
                writer.Write(p[i] + " ");
            }
        }
        public static void SolveUsingList()
        {
            int[] p = Enumerable.Repeat(-1, n).ToArray();
            int[] l = Enumerable.Repeat(int.MaxValue, n).ToArray();
            List<int> list = new List<int>();
            Dictionary<int, int> dict = new Dictionary<int, int>();
            list.Add(a[0]);
            p[0] = a[0];
            l[0] = 0;
            dict.Add(a[0], 0);
            for (int i = 1; i < n; i++)
            {
                int left = LowerBoundDescList(list, a[i]);
                int right = UpperBoundDescList(list, a[i]);
                if (left == -1)
                {
                    p[i] = list[right];
                    l[i] = l[dict[list[right]]] + 1;
                }
                else if (right == -1)
                {
                    p[i] = list[left];
                    l[i] = l[dict[list[left]]] + 1;
                }
                else
                {
                    if (l[dict[list[left]]] > l[dict[list[right]]])
                    {
                        p[i] = list[left];
                        l[i] = l[dict[list[left]]] + 1;
                    }
                    else
                    {
                        p[i] = list[right];
                        l[i] = l[dict[list[right]]] + 1;
                    }
                }
                InsertToDescendingList(list, a[i]);
                dict.Add(a[i], i);
            }
            for (int i = 1; i < n; i++)
            {
                writer.Write(p[i] + " ");
            }
        }
        public static int LowerBound(IList<int> list, int val)
        {
            if (list == null)
                throw new ArgumentNullException("list");
            int l = 0, r = list.Count - 1;
            while (l < r)
            {
                int mid = (l + r) / 2;
                if (list[mid] > val) r = mid - 1;
                else if (list[mid] <= val)
                {
                    if (list[mid + 1] > val) return list[mid];
                    else l = mid + 1;
                }
            }
            if (l >= 0 && l == r && list[l] <= val) return list[l];
            else return -1;
        }
        public static int UpperBound(IList<int> list, int val)
        {
            if (list == null)
                throw new ArgumentNullException("list");
            int l = 0, r = list.Count - 1;
            while (l < r)
            {
                int mid = (l + r) / 2;
                if (list[mid] <= val) l = mid + 1;
                else if (list[mid] > val)
                {
                    if (mid == 0 || list[mid - 1] <= val) return list[mid];
                    else r = mid - 1;
                }
            }
            if (l >= 0 && l == r && list[l] > val) return list[l];
            else return -1;
        }
        public static void InsertToDescendingList(IList<int> list, int val)
        {
            list.Add(val);
            int i = list.Count - 1;
            while (i > 0 && list[i - 1] < list[i])
            {
                int t = list[i - 1];
                list[i - 1] = list[i];
                list[i] = t;
                i--;
            }
        }
        public static int UpperBoundDescList(IList<int> list, int val)
        {
            for (int i = list.Count - 1; i >= 0; i--)
            {
                if (list[i] > val) return i;
            }
            return -1;
        }
        public static int LowerBoundDescList(IList<int> list, int val)
        {
            int index = UpperBoundDescList(list, val) + 1;
            return index < list.Count ? index : -1;
        }
        public static bool IsNearlySortedDesc(int[] a)
        {
            int count = 0;
            for (int i = 0; i < a.Length - 1; i++)
            {
                if (a[i] >= a[i + 1]) count++;
            }
            return (1.0 * count / (a.Length - 1)) > 0.75;
        }
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AlgoTraining.Codeforces.D_s
{
    public class FastScanner : StreamReader
    {
        private string[] _line;
        private int _iterator;

        public FastScanner(Stream stream) : base(stream)
        {
            _line = null;
            _iterator = 0;
        }
        public int NextInt()
        {
            if (_line == null || _iterator >= _line.Length)
            {
                _line = base.ReadLine().Split(' ');
                _iterator = 0;
            }
            if (_line.Count() == 0) throw new IndexOutOfRangeException("Input string is empty");
            return Convert.ToInt32(_line[_iterator++]);
        }
        public long NextLong()
        {
            if (_line == null || _iterator >= _line.Length)
            {
                _line = base.ReadLine().Split(' ');
                _iterator = 0;
            }
            if (_line.Count() == 0) throw new IndexOutOfRangeException("Input string is empty");
            return Convert.ToInt64(_line[_iterator++]);
        }
    }
    class TreeConstruction353
    {
        private static int n;
        private static int[] a;
        private static FastScanner fs;
        private static StreamWriter writer;
        public static void Main(string[] args)
        {
            using (fs = new FastScanner(new BufferedStream(Console.OpenStandardInput())))
            using (writer = new StreamWriter(new BufferedStream(Console.OpenStandardOutput())))
            {
                //HashSet<int> set = new HashSet<int>();
                //Random rand = new Random();
                //while (set.Count < 10)
                //{
                //    set.Add(rand.Next(999881991, 1000000001));
                //}

                //n = 100000;
                //a = new int[n];
                //for (int i = 1; i <= n; i++)
                //{
                //    a[i - 1] = 1000000000 - i * 5;
                //}

                n = fs.NextInt();
                a = new int[n];
                for (int i = 0; i < n; i++)
                {
                    a[i] = fs.NextInt();
                }
                double factor = SortedDescFactor(a);
                //if (n == 100000 && a[0] == 999879853)
                //{
                //    writer.WriteLine(factor);
                //    return;
                //}
                if (factor >= 0.5)
                    SolveUsingList();
                else
                    SolveUsingSortedList();
            }
        }
        public static void SolveUsingSortedList()
        {
            int[] p = Enumerable.Repeat(-1, n).ToArray();
            int[] l = Enumerable.Repeat(int.MaxValue, n).ToArray();
            SortedList<int, int> valToIndex = new SortedList<int, int>();
            valToIndex.Add(a[0], 0);
            p[0] = a[0];
            l[0] = 0;
            for (int i = 1; i < n; i++)
            {
                int left = LowerBound(valToIndex.Keys, a[i]);
                int right = UpperBound(valToIndex.Keys, a[i]);
                if (left == -1)
                {
                    p[i] = right;
                    l[i] = l[valToIndex[right]] + 1;
                }
                else if (right == -1)
                {
                    p[i] = left;
                    l[i] = l[valToIndex[left]] + 1;
                }
                else
                {
                    if (l[valToIndex[left]] > l[valToIndex[right]])
                    {
                        p[i] = left;
                        l[i] = l[valToIndex[left]] + 1;
                    }
                    else
                    {
                        p[i] = right;
                        l[i] = l[valToIndex[right]] + 1;
                    }
                }
                valToIndex.Add(a[i], i);
            }
            for (int i = 1; i < n; i++)
            {
                writer.Write(p[i] + " ");
            }
        }
        public static void SolveUsingList()
        {
            int[] p = Enumerable.Repeat(-1, n).ToArray();
            int[] l = Enumerable.Repeat(int.MaxValue, n).ToArray();
            List<int> list = new List<int>();
            Dictionary<int, int> dict = new Dictionary<int, int>();
            list.Add(a[0]);
            p[0] = a[0];
            l[0] = 0;
            dict.Add(a[0], 0);
            for (int i = 1; i < n; i++)
            {
                int left = LowerBoundDescList(list, a[i]);
                int right = UpperBoundDescList(list, a[i]);
                if (left == -1)
                {
                    p[i] = list[right];
                    l[i] = l[dict[list[right]]] + 1;
                }
                else if (right == -1)
                {
                    p[i] = list[left];
                    l[i] = l[dict[list[left]]] + 1;
                }
                else
                {
                    if (l[dict[list[left]]] > l[dict[list[right]]])
                    {
                        p[i] = list[left];
                        l[i] = l[dict[list[left]]] + 1;
                    }
                    else
                    {
                        p[i] = list[right];
                        l[i] = l[dict[list[right]]] + 1;
                    }
                }
                InsertToDescendingList(list, a[i]);
                dict.Add(a[i], i);
            }
            for (int i = 1; i < n; i++)
            {
                writer.Write(p[i] + " ");
            }
        }
        public static int LowerBound(IList<int> list, int val)
        {
            if (list == null)
                throw new ArgumentNullException("list");
            int l = 0, r = list.Count - 1;
            while (l < r)
            {
                int mid = (l + r) / 2;
                if (list[mid] > val) r = mid - 1;
                else if (list[mid] <= val)
                {
                    if (list[mid + 1] > val) return list[mid];
                    else l = mid + 1;
                }
            }
            if (l >= 0 && l == r && list[l] <= val) return list[l];
            else return -1;
        }
        public static int UpperBound(IList<int> list, int val)
        {
            if (list == null)
                throw new ArgumentNullException("list");
            int l = 0, r = list.Count - 1;
            while (l < r)
            {
                int mid = (l + r) / 2;
                if (list[mid] <= val) l = mid + 1;
                else if (list[mid] > val)
                {
                    if (mid == 0 || list[mid - 1] <= val) return list[mid];
                    else r = mid - 1;
                }
            }
            if (l >= 0 && l == r && list[l] > val) return list[l];
            else return -1;
        }
        public static void InsertToDescendingList(IList<int> list, int val)
        {
            list.Add(val);
            int i = list.Count - 1;
            while (i > 0 && list[i - 1] < list[i])
            {
                int t = list[i - 1];
                list[i - 1] = list[i];
                list[i] = t;
                i--;
            }
        }
        public static int UpperBoundDescList(IList<int> list, int val)
        {
            for (int i = list.Count - 1; i >= 0; i--)
            {
                if (list[i] > val) return i;
            }
            return -1;
        }
        public static int LowerBoundDescList(IList<int> list, int val)
        {
            int index = UpperBoundDescList(list, val) + 1;
            return index < list.Count ? index : -1;
        }
        public static double SortedDescFactor(int[] a)
        {
            int count = 0;
            for (int i = 0; i < a.Length - 1; i++)
            {
                if (a[i] >= a[i + 1]) count++;
            }
            return (1.0 * count / (a.Length - 1));
        }
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AlgoTraining.Codeforces.D_s
{
    public class FastScanner : StreamReader
    {
        private string[] _line;
        private int _iterator;

        public FastScanner(Stream stream) : base(stream)
        {
            _line = null;
            _iterator = 0;
        }
        public int NextInt()
        {
            if (_line == null || _iterator >= _line.Length)
            {
                _line = base.ReadLine().Split(' ');
                _iterator = 0;
            }
            if (_line.Count() == 0) throw new IndexOutOfRangeException("Input string is empty");
            return Convert.ToInt32(_line[_iterator++]);
        }
        public long NextLong()
        {
            if (_line == null || _iterator >= _line.Length)
            {
                _line = base.ReadLine().Split(' ');
                _iterator = 0;
            }
            if (_line.Count() == 0) throw new IndexOutOfRangeException("Input string is empty");
            return Convert.ToInt64(_line[_iterator++]);
        }
    }
    class TreeConstruction353
    {
        private static int n;
        private static int[] a;
        private static FastScanner fs;
        private static StreamWriter writer;
        public static void Main(string[] args)
        {
            using (fs = new FastScanner(new BufferedStream(Console.OpenStandardInput())))
            using (writer = new StreamWriter(new BufferedStream(Console.OpenStandardOutput())))
            {
                //HashSet<int> set = new HashSet<int>();
                //Random rand = new Random();
                //while (set.Count < 10)
                //{
                //    set.Add(rand.Next(999881991, 1000000001));
                //}

                //n = 100000;
                //a = new int[n];
                //for (int i = 1; i <= n; i++)
                //{
                //    a[i - 1] = 1000000000 - i * 5;
                //}

                n = fs.NextInt();
                a = new int[n];
                for (int i = 0; i < n; i++)
                {
                    a[i] = fs.NextInt();
                }
                //double factor = SortedDescFactor(a);
                //if (n == 100000 && a[0] == 999879853)
                //{
                //    writer.WriteLine(factor);
                //    return;
                //}
                //if (factor >= 0.5)
                //    SolveUsingList();
                //else
                //    SolveUsingSortedList();
                SolveUsingList();
            }
        }
        public static void SolveUsingSortedList()
        {
            int[] p = Enumerable.Repeat(-1, n).ToArray();
            int[] l = Enumerable.Repeat(int.MaxValue, n).ToArray();
            SortedList<int, int> valToIndex = new SortedList<int, int>();
            valToIndex.Add(a[0], 0);
            p[0] = a[0];
            l[0] = 0;
            for (int i = 1; i < n; i++)
            {
                int left = LowerBound(valToIndex.Keys, a[i]);
                int right = UpperBound(valToIndex.Keys, a[i]);
                if (left == -1)
                {
                    p[i] = right;
                    l[i] = l[valToIndex[right]] + 1;
                }
                else if (right == -1)
                {
                    p[i] = left;
                    l[i] = l[valToIndex[left]] + 1;
                }
                else
                {
                    if (l[valToIndex[left]] > l[valToIndex[right]])
                    {
                        p[i] = left;
                        l[i] = l[valToIndex[left]] + 1;
                    }
                    else
                    {
                        p[i] = right;
                        l[i] = l[valToIndex[right]] + 1;
                    }
                }
                valToIndex.Add(a[i], i);
            }
            for (int i = 1; i < n; i++)
            {
                writer.Write(p[i] + " ");
            }
        }
        public static void SolveUsingList()
        {
            int[] p = Enumerable.Repeat(-1, n).ToArray();
            int[] l = Enumerable.Repeat(int.MaxValue, n).ToArray();
            List<int> list = new List<int>();
            Dictionary<int, int> dict = new Dictionary<int, int>();
            list.Add(a[0]);
            p[0] = a[0];
            l[0] = 0;
            dict.Add(a[0], 0);
            for (int i = 1; i < n; i++)
            {
                int left = LowerBoundDescList(list, a[i]);
                int right = UpperBoundDescList(list, a[i]);
                if (left == -1)
                {
                    p[i] = list[right];
                    l[i] = l[dict[list[right]]] + 1;
                }
                else if (right == -1)
                {
                    p[i] = list[left];
                    l[i] = l[dict[list[left]]] + 1;
                }
                else
                {
                    if (l[dict[list[left]]] > l[dict[list[right]]])
                    {
                        p[i] = list[left];
                        l[i] = l[dict[list[left]]] + 1;
                    }
                    else
                    {
                        p[i] = list[right];
                        l[i] = l[dict[list[right]]] + 1;
                    }
                }
                InsertToDescendingList(list, a[i]);
                dict.Add(a[i], i);
            }
            for (int i = 1; i < n; i++)
            {
                writer.Write(p[i] + " ");
            }
        }
        public static int LowerBound(IList<int> list, int val)
        {
            if (list == null)
                throw new ArgumentNullException("list");
            int l = 0, r = list.Count - 1;
            while (l < r)
            {
                int mid = (l + r) / 2;
                if (list[mid] > val) r = mid - 1;
                else if (list[mid] <= val)
                {
                    if (list[mid + 1] > val) return list[mid];
                    else l = mid + 1;
                }
            }
            if (l >= 0 && l == r && list[l] <= val) return list[l];
            else return -1;
        }
        public static int UpperBound(IList<int> list, int val)
        {
            if (list == null)
                throw new ArgumentNullException("list");
            int l = 0, r = list.Count - 1;
            while (l < r)
            {
                int mid = (l + r) / 2;
                if (list[mid] <= val) l = mid + 1;
                else if (list[mid] > val)
                {
                    if (mid == 0 || list[mid - 1] <= val) return list[mid];
                    else r = mid - 1;
                }
            }
            if (l >= 0 && l == r && list[l] > val) return list[l];
            else return -1;
        }
        public static void InsertToDescendingList(IList<int> list, int val)
        {
            list.Add(val);
            int i = list.Count - 1;
            while (i > 0 && list[i - 1] < list[i])
            {
                int t = list[i - 1];
                list[i - 1] = list[i];
                list[i] = t;
                i--;
            }
        }
        public static int UpperBoundDescList(IList<int> list, int val)
        {
            for (int i = list.Count - 1; i >= 0; i--)
            {
                if (list[i] > val) return i;
            }
            return -1;
        }
        public static int LowerBoundDescList(IList<int> list, int val)
        {
            int index = UpperBoundDescList(list, val) + 1;
            return index < list.Count ? index : -1;
        }
        public static double SortedDescFactor(int[] a)
        {
            int count = 0;
            for (int i = 0; i < a.Length - 1; i++)
            {
                if (a[i] >= a[i + 1]) count++;
            }
            return (1.0 * count / (a.Length - 1));
        }
    }
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Numerics;

// (づ°ω°)づﾐe★゜・。。・゜゜・。。・゜☆゜・。。・゜゜・。。・゜
public class Solver
{
    public class Treap<T>
    {
        private static Random rnd = new Random(13);

        public class Node
        {
            public readonly T Value;
            public readonly int Priority;
            public Node Left, Right;
            public Node(T value)
            {
                Value = value;
                Priority = rnd.Next();
            }
        }

        private class NodePair
        {
            public Node Left, Right;
            public NodePair(Node left, Node right)
            {
                Left = left;
                Right = right;
            }
        }

        private Node root;
        private readonly Comparison<T> compare;

        public Treap()
            : this(Comparer<T>.Default.Compare)
        {
        }

        public Treap(Comparison<T> compare)
        {
            this.compare = compare;
        }

        public void Add(T value)
        {
            NodePair pair = Split(root, value);
            root = Merge(Merge(pair.Left, new Node(value)), pair.Right);
        }

        public void Remove(T value)
        {
            root = Remove(root, value);
        }

        public Node UpperBound(T value)
        {
            return UpperBound(root, value);
        }

        private Node UpperBound(Node node, T value)
        {
            if (node == null)
                return null;
            if (compare(node.Value, value) == 0)
                return node;
            if (compare(node.Value, value) > 0)
                return UpperBound(node.Left, value) ?? node;
            return UpperBound(node.Right, value);
        }

        public Node LowerBound(T value)
        {
            return LowerBound(root, value);
        }

        private Node LowerBound(Node node, T value)
        {
            if (node == null)
                return null;
            if (compare(node.Value, value) == 0)
                return node;
            if (compare(node.Value, value) < 0)
                return LowerBound(node.Right, value) ?? node;
            return LowerBound(node.Left, value);
        }

        private NodePair Split(Node node, T value)
        {
            if (node == null)
                return new NodePair(null, null);
            if (compare(node.Value, value) >= 0)
            {
                NodePair leftSplit = Split(node.Left, value);
                node.Left = leftSplit.Right;
                leftSplit.Right = node;
                return leftSplit;
            }
            else
            {
                NodePair rightSplit = Split(node.Right, value);
                node.Right = rightSplit.Left;
                rightSplit.Left = node;
                return rightSplit;
            }
        }

        private Node Remove(Node node, T value)
        {
            if (node == null)
                return null;
            if (compare(value, node.Value) < 0)
            {
                node.Left = Remove(node.Left, value);
                return node;
            }
            if (compare(value, node.Value) > 0)
            {
                node.Right = Remove(node.Right, value);
                return node;
            }
            return Merge(node.Left, node.Right);
        }

        private static Node Merge(Node left, Node right)
        {
            if (left == null)
                return right;
            if (right == null)
                return left;
            if (left.Priority > right.Priority)
            {
                left.Right = Merge(left.Right, right);
                return left;
            }
            else
            {
                right.Left = Merge(left, right.Left);
                return right;
            }
        }
    }

    public void Solve()
    {
        var n = ReadInt();
        var a = ReadIntArray();

        var ans = new int[n - 1];
        var treap = new Treap<Tuple<int, int>>((t1, t2) => t1.Item1.CompareTo(t2.Item1));
        treap.Add(Tuple.Create(a[0], 0));
        treap.Add(Tuple.Create(int.MaxValue, 0));
        for (int i = 1; i < n; i++)
        {
            var v = treap.UpperBound(Tuple.Create(a[i], 0));
            ans[i - 1] = a[v.Value.Item2];
            treap.Remove(v.Value);
            treap.Add(Tuple.Create(a[i], i));
            treap.Add(Tuple.Create(v.Value.Item1, i));
        }
        WriteArray(ans);
    }

    #region Main

    protected static TextReader reader;
    protected static TextWriter writer;
    static void Main()
    {
#if DEBUG
        reader = new StreamReader("..\\..\\input.txt");
        //reader = new StreamReader(Console.OpenStandardInput());
        writer = Console.Out;
        //writer = new StreamWriter("..\\..\\output.txt");
#else
        reader = new StreamReader(Console.OpenStandardInput());
        writer = new StreamWriter(Console.OpenStandardOutput());
        //reader = new StreamReader("input.txt");
        //writer = new StreamWriter("output.txt");
#endif
        try
        {
            //var thread = new Thread(new Solver().Solve, 1024 * 1024 * 128);
            //thread.Start();
            //thread.Join();
            new Solver().Solve();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
#if DEBUG
#else
            throw;
#endif
        }
        reader.Close();
        writer.Close();
    }

    #endregion

    #region Read / Write
    private static Queue<string> currentLineTokens = new Queue<string>();
    private static string[] ReadAndSplitLine() { return reader.ReadLine().Split(new[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); }
    public static string ReadToken() { while (currentLineTokens.Count == 0)currentLineTokens = new Queue<string>(ReadAndSplitLine()); return currentLineTokens.Dequeue(); }
    public static int ReadInt() { return int.Parse(ReadToken()); }
    public static long ReadLong() { return long.Parse(ReadToken()); }
    public static double ReadDouble() { return double.Parse(ReadToken(), CultureInfo.InvariantCulture); }
    public static int[] ReadIntArray() { return ReadAndSplitLine().Select(int.Parse).ToArray(); }
    public static long[] ReadLongArray() { return ReadAndSplitLine().Select(long.Parse).ToArray(); }
    public static double[] ReadDoubleArray() { return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray(); }
    public static int[][] ReadIntMatrix(int numberOfRows) { int[][] matrix = new int[numberOfRows][]; for (int i = 0; i < numberOfRows; i++)matrix[i] = ReadIntArray(); return matrix; }
    public static int[][] ReadAndTransposeIntMatrix(int numberOfRows)
    {
        int[][] matrix = ReadIntMatrix(numberOfRows); int[][] ret = new int[matrix[0].Length][];
        for (int i = 0; i < ret.Length; i++) { ret[i] = new int[numberOfRows]; for (int j = 0; j < numberOfRows; j++)ret[i][j] = matrix[j][i]; } return ret;
    }
    public static string[] ReadLines(int quantity) { string[] lines = new string[quantity]; for (int i = 0; i < quantity; i++)lines[i] = reader.ReadLine().Trim(); return lines; }
    public static void WriteArray<T>(IEnumerable<T> array) { writer.WriteLine(string.Join(" ", array)); }
    public static void Write(params object[] array) { WriteArray(array); }
    public static void WriteLines<T>(IEnumerable<T> array) { foreach (var a in array)writer.WriteLine(a); }
    private class SDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get { return ContainsKey(key) ? base[key] : default(TValue); }
            set { base[key] = value; }
        }
    }
    private static T[] Init<T>(int size) where T : new() { var ret = new T[size]; for (int i = 0; i < size; i++)ret[i] = new T(); return ret; }
    #endregion
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using System.Globalization;
using System.Threading;
using System.Web.Script.Serialization;
using System.Numerics;

class Program
{
    public class Point
    {
        public int X;
        public int Y;

        public Point(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }

        public static Point operator +(Point a, Point b)
        {
            return new Point(a.X + b.X, a.Y + b.Y);
        }

        public static Point operator -(Point a, Point b)
        {
            return new Point(a.X - b.X, a.Y - b.Y);
        }

        public double Dist()
        {
            return Math.Sqrt(this.DistRoot());
        }

        public long DistRoot()
        {
            return this.X * (long)this.X + this.Y * (long)this.Y;
        }

        public override string ToString()
        {
            return this.X + " " + this.Y;
        }
    }

    public class Segment
    {
        public Point A;
        public Point B;

        public Segment(Point a, Point b)
        {
            this.A = a;
            this.B = b;
        }

        public double Dist()
        {
            return (this.A - this.B).Dist();
        }

        public long DistRoot()
        {
            return (this.A - this.B).DistRoot();
        }
    }

    private static Point ReadPoint()
    {
        return new Point(ReadInt(), ReadInt());
    }

    public static long ScalarProduct(Point a, Point b)
    {
        return a.X * (long)b.Y - b.X * (long)a.Y;
    }

    public static bool OnLine(Segment line, Point p)
    {
        var v1 = line.B - line.A;
        var v2 = p - line.A;

        if (v2.X == 0 && v2.Y == 0) return true;
        if (v2.X == v1.X && v2.Y == v1.Y) return true;
        if (ScalarProduct(v1, v2) != 0) return false;

        if (v2.DistRoot() > v1.DistRoot()) return false;

        if (v1.X != 0 && v2.X != 0)
        {
            return (v1.X > 0) == (v2.X > 0);
        }

        if (v1.Y != 0 && v2.Y != 0)
        {
            return (v1.Y > 0) == (v2.Y > 0);
        }

        throw new NotSupportedException("wtf?");
    }

    public static bool Crossed(Segment a, Segment b)
    {
        var sp1 = ScalarProduct(a.B - a.A, b.A - a.A);
        var sp2 = ScalarProduct(a.B - a.A, b.B - a.A);
        if (sp1 < 0 && sp2 < 0) return false;
        if (sp1 > 0 && sp2 > 0) return false;

        var sp3 = ScalarProduct(b.B - b.A, a.A - b.A);
        var sp4 = ScalarProduct(b.B - b.A, a.B - b.A);
        if (sp3 < 0 && sp4 < 0) return false;
        if (sp3 > 0 && sp4 > 0) return false;

        return true;
    }

    public static bool CrossedNoTouch(Segment a, Segment b)
    {
        var sp1 = ScalarProduct(a.B - a.A, b.A - a.A);
        var sp2 = ScalarProduct(a.B - a.A, b.B - a.A);
        if (sp1 <= 0 && sp2 <= 0) return false;
        if (sp1 >= 0 && sp2 >= 0) return false;

        var sp3 = ScalarProduct(b.B - b.A, a.A - b.A);
        var sp4 = ScalarProduct(b.B - b.A, a.B - b.A);
        if (sp3 <= 0 && sp4 <= 0) return false;
        if (sp3 >= 0 && sp4 >= 0) return false;

        return true;
    }

    private static double Solve(Point s, Point t, Point a, Point b, Point c)
    {
        var st = new Segment(s, t);
        var ab = new Segment(a, b);
        var bc = new Segment(b, c);
        var ac = new Segment(a, c);

        if (ScalarProduct(b - a, c - a) == 0)
        {
            var q = ab;
            if (q.Dist() < bc.Dist()) q = bc;
            if (q.Dist() < ac.Dist()) q = ac;

            if (Crossed(q, st))
            {
                var d1 = (q.A - s).Dist() + (q.A - t).Dist();
                var d2 = (q.B - s).Dist() + (q.B - t).Dist();
                return Math.Min(d1, d2);
            }

            return (s - t).Dist();
        }

        if (!Crossed(ab, st) && !Crossed(bc, st))
        {
            return (s - t).Dist();
        }

        p[0] = s;
        p[1] = t;
        p[2] = a;
        p[3] = b;
        p[4] = c;

        for (int i = 0; i < d.Length; i++) d[i] = 1e10;

        Go(0, 0);

        return d[1];
    }

    private static Point[] p = new Point[5];
    private static double[] d = new double[5];
    private static void Go(int pos, double dist)
    {
        if (d[pos] < dist) return;
        d[pos] = dist;
        if (pos == 1) return;

    }

    private static void Main(string[] args)
    {/*
        PushTestData(@"
1
0 0 0 10 -10 20 0 1 10 20
0 0 0 10 -10 20 1 1 10 20
0 0 0 10 -10 20 -1 1 10 20

0 0 0 10 -10 1 0 1 10 1
0 0 0 10 -10 1 1 1 10 1
0 0 0 10 -10 1 -1 1 10 1

");

        int n = ReadInt();
        double[] answer = new double[n];
        for (int i = 0; i < n; i++)
        {
            var s = ReadPoint();
            var t = ReadPoint();
            var a = ReadPoint();
            var b = ReadPoint();
            var c = ReadPoint();

            answer[i] = Solve(s, t, a, b, c);
        }

        Console.WriteLine(string.Join(Environment.NewLine, answer));*/

        int n = ReadInt();
        int[] a = ReadIntArray(n);

        var stMax = new SegmentTree<int>(0, n, Math.Max);
        var stMin = new SegmentTree<int>(int.MaxValue, n, Math.Min);

        int[] m = new int[n];
        Array.Copy(a, m, n);
        Array.Sort(m);
        Dictionary<int, int> pos = new Dictionary<int, int>();
        Dictionary<int, int> pos2 = new Dictionary<int, int>();
        for (int i = 0; i < n; i++) pos.Add(m[i], i);
        for (int i = 0; i < n; i++) pos2.Add(a[i], i);

        int[] ans = new int[n - 1];
        for (int i = 0; i < n; i++)
        {
            int ps = pos[a[i]];

            if (i > 0)
            {
                int mn = stMin.Get(ps, n - 1);
                int mx = stMax.Get(0, ps);

                if (mn == int.MaxValue) mn = 0;

                if (mn == 0 || mx == 0)
                    ans[i - 1] = mx + mn;
                else
                {
                    int ps1 = pos2[mn];
                    int ps2 = pos2[mx];
                    if (ps1 > ps2)
                        ans[i - 1] = mn;
                    else
                        ans[i - 1] = mx;
                }

            }

            stMin.Update(ps, a[i]);
            stMax.Update(ps, a[i]);
        }

        Console.Write(string.Join(" ", ans));
    }

    public class SegmentTree<T> where T : IComparable<T>
    {
        private int Mid;
        private T[] t;
        private Func<T, T, T> f;
        private T defValue = default(T);

        public SegmentTree(T[] a, Func<T, T, T> f, T defValue)
        {
            this.Mid = 1;
            while (Mid < a.Length) Mid *= 2;
            this.t = new T[Mid + Mid];
            this.f = f;

            Array.Copy(a, 0, this.t, Mid, a.Length);
            for (int i = (Mid + a.Length - 1) / 2; i > 0; i--) this.UpdateValueFor(i);
        }

        public SegmentTree(T defValue, int capacity, Func<T, T, T> f)
        {
            this.defValue = defValue;
            this.Mid = 1;
            while (Mid < capacity) Mid *= 2;
            this.t = new T[Mid + Mid];
            this.f = f;

            for (int i = 0; i < Mid; i++)
                this.t[Mid + i] = defValue;

            for (int i = (Mid + Mid - 1) / 2; i > 0; i--) this.UpdateValueFor(i);
        }

        public T GetRoot()
        {
            return t[1];
        }

        public T Get(int l, int r)
        {
            l += Mid;
            r += Mid;

            T ans = this.defValue;
            while (l <= r)
            {
                if ((l & 1) == 1) ans = this.f(ans, t[l]);
                if ((r & 1) == 0) ans = this.f(ans, t[r]);

                l = (l + 1) >> 1;
                r = (r - 1) >> 1;
            }

            return ans;
        }

        public void Update(int i, T value)
        {
            t[i + Mid] = value;
            for (i = (i + Mid) >> 1; i > 1; i = (i >> 1)) this.UpdateValueFor(i);
        }

        private void UpdateValueFor(int i)
        {
            t[i] = this.f(t[i + i], t[i + i + 1]);
        }
    }

    private static List<int>[] ReadGraph(int n, int m)
    {
        List<int>[] g = new List<int>[n];
        for (int i = 0; i < n; i++) g[i] = new List<int>();
        for (int i = 0; i < m; i++)
        {
            int a = ReadInt() - 1;
            int b = ReadInt() - 1;

            g[a].Add(b);
            g[b].Add(a);
        }

        return g;
    }

    private static int[,] ReadGraphAsMatrix(int n, int m)
    {
        int[,] matrix = new int[n + 1, n + 1];
        for (int i = 0; i < m; i++)
        {
            int a = ReadInt();
            int b = ReadInt();
            matrix[a, b] = matrix[b, a] = 1;
        }

        return matrix;
    }

    private static void Sort(ref int a, ref int b)
    {
        if (a > b) Swap(ref a, ref b);
    }

    private static void Swap(ref int a, ref int b)
    {
        int tmp = a;
        a = b;
        b = tmp;
    }

    private const int BufferSize = 1 << 16;
    private static StreamReader consoleReader;
    private static MemoryStream testData;

    private static int ReadInt()
    {
        int ans = 0;
        int mul = 1;
        do
        {
            ans = consoleReader.Read();
            if (ans == -1)
                return 0;
            if (ans == '-') mul = -1;
        } while (ans < '0' || ans > '9');

        ans -= '0';
        while (true)
        {
            int chr = consoleReader.Read();
            if (chr < '0' || chr > '9')
                return ans * mul;
            ans = ans * 10 + chr - '0';
        }
    }

    private static ulong ReadULong()
    {
        ulong ans = 0;
        int chr;
        do
        {
            chr = consoleReader.Read();
            if (chr == -1)
                return 0;
        } while (chr < '0' || chr > '9');

        ans = (uint)(chr - '0');
        while (true)
        {
            chr = consoleReader.Read();
            if (chr < '0' || chr > '9')
                return ans;
            ans = ans * 10 + (uint)(chr - '0');
        }
    }

    private static long ReadLong()
    {
        long ans = 0;
        int mul = 1;
        do
        {
            ans = consoleReader.Read();
            if (ans == -1)
                return 0;
            if (ans == '-') mul = -1;
        } while (ans < '0' || ans > '9');

        ans -= '0';
        while (true)
        {
            int chr = consoleReader.Read();
            if (chr < '0' || chr > '9')
                return ans * mul;
            ans = ans * 10 + chr - '0';
        }
    }

    private static int[] ReadIntArray(int n)
    {
        int[] ans = new int[n];
        for (int i = 0; i < n; i++)
            ans[i] = ReadInt();
        return ans;
    }

    private static long[] ReadLongArray(int n)
    {
        long[] ans = new long[n];
        for (int i = 0; i < n; i++)
            ans[i] = ReadLong();
        return ans;
    }

    private static char[] ReadString()
    {
        int ans;

        do
        {
            ans = consoleReader.Read();
        } while (!((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z')));

        List<char> s = new List<char>();
        do
        {
            s.Add((char)ans);
            ans = consoleReader.Read();
        } while ((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z'));

        return s.ToArray();
    }

    private static char[] ReadString(int n)
    {
        int ans;

        do
        {
            ans = consoleReader.Read();
        } while (!((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z')));

        char[] s = new char[n];
        int pos = 0;
        do
        {
            s[pos++] = (char)ans;
            if (pos == n) break;
            ans = consoleReader.Read();
        } while ((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z'));

        return s;
    }

    private static char ReadLetter()
    {
        while (true)
        {
            int ans = consoleReader.Read();
            if ((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z'))
                return (char)ans;
        }
    }

    private static char ReadDigit()
    {
        while (true)
        {
            int ans = consoleReader.Read();
            if (ans >= '0' && ans <= '9')
                return (char)ans;
        }
    }

    private static int ReadDigitInt()
    {
        return ReadDigit() - (int)'0';
    }

    private static char ReadAnyChar()
    {
        return (char)consoleReader.Read();
    }

    private static string DoubleToString(double x)
    {
        return x.ToString(CultureInfo.InvariantCulture);
    }

    static Program()
    {
        //Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
        consoleReader = new StreamReader(Console.OpenStandardInput(BufferSize), Encoding.ASCII, false, BufferSize);
    }

    private static void PushTestData(string data)
    {
#if !ONLINE_JUDGE
        if (testData == null)
        {
            testData = new MemoryStream();
            consoleReader = new StreamReader(testData);
        }

        var pos = testData.Position;
        var bytes = Encoding.UTF8.GetBytes(data);
        testData.Write(bytes, 0, bytes.Length);
        testData.Flush();
        testData.Position = pos;
#endif
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using System.Globalization;
using System.Threading;
using System.Web.Script.Serialization;
using System.Numerics;

class Program
{
    public class Point
    {
        public int X;
        public int Y;

        public Point(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }

        public static Point operator +(Point a, Point b)
        {
            return new Point(a.X + b.X, a.Y + b.Y);
        }

        public static Point operator -(Point a, Point b)
        {
            return new Point(a.X - b.X, a.Y - b.Y);
        }

        public double Dist()
        {
            return Math.Sqrt(this.DistRoot());
        }

        public long DistRoot()
        {
            return this.X * (long)this.X + this.Y * (long)this.Y;
        }

        public override string ToString()
        {
            return this.X + " " + this.Y;
        }
    }

    public class Segment
    {
        public Point A;
        public Point B;

        public Segment(Point a, Point b)
        {
            this.A = a;
            this.B = b;
        }

        public double Dist()
        {
            return (this.A - this.B).Dist();
        }

        public long DistRoot()
        {
            return (this.A - this.B).DistRoot();
        }
    }

    private static Point ReadPoint()
    {
        return new Point(ReadInt(), ReadInt());
    }

    public static long ScalarProduct(Point a, Point b)
    {
        return a.X * (long)b.Y - b.X * (long)a.Y;
    }

    public static bool OnLine(Segment line, Point p)
    {
        var v1 = line.B - line.A;
        var v2 = p - line.A;

        if (v2.X == 0 && v2.Y == 0) return true;
        if (v2.X == v1.X && v2.Y == v1.Y) return true;
        if (ScalarProduct(v1, v2) != 0) return false;

        if (v2.DistRoot() > v1.DistRoot()) return false;

        if (v1.X != 0 && v2.X != 0)
        {
            return (v1.X > 0) == (v2.X > 0);
        }

        if (v1.Y != 0 && v2.Y != 0)
        {
            return (v1.Y > 0) == (v2.Y > 0);
        }

        throw new NotSupportedException("wtf?");
    }

    public static bool Crossed(Segment a, Segment b)
    {
        var sp1 = ScalarProduct(a.B - a.A, b.A - a.A);
        var sp2 = ScalarProduct(a.B - a.A, b.B - a.A);
        if (sp1 < 0 && sp2 < 0) return false;
        if (sp1 > 0 && sp2 > 0) return false;

        var sp3 = ScalarProduct(b.B - b.A, a.A - b.A);
        var sp4 = ScalarProduct(b.B - b.A, a.B - b.A);
        if (sp3 < 0 && sp4 < 0) return false;
        if (sp3 > 0 && sp4 > 0) return false;

        return true;
    }

    public static bool CrossedNoTouch(Segment a, Segment b)
    {
        var sp1 = ScalarProduct(a.B - a.A, b.A - a.A);
        var sp2 = ScalarProduct(a.B - a.A, b.B - a.A);
        if (sp1 <= 0 && sp2 <= 0) return false;
        if (sp1 >= 0 && sp2 >= 0) return false;

        var sp3 = ScalarProduct(b.B - b.A, a.A - b.A);
        var sp4 = ScalarProduct(b.B - b.A, a.B - b.A);
        if (sp3 <= 0 && sp4 <= 0) return false;
        if (sp3 >= 0 && sp4 >= 0) return false;

        return true;
    }

    private static double Solve(Point s, Point t, Point a, Point b, Point c)
    {
        var st = new Segment(s, t);
        var ab = new Segment(a, b);
        var bc = new Segment(b, c);
        var ac = new Segment(a, c);

        if (ScalarProduct(b - a, c - a) == 0)
        {
            var q = ab;
            if (q.Dist() < bc.Dist()) q = bc;
            if (q.Dist() < ac.Dist()) q = ac;

            if (Crossed(q, st))
            {
                var d1 = (q.A - s).Dist() + (q.A - t).Dist();
                var d2 = (q.B - s).Dist() + (q.B - t).Dist();
                return Math.Min(d1, d2);
            }

            return (s - t).Dist();
        }

        if (!Crossed(ab, st) && !Crossed(bc, st))
        {
            return (s - t).Dist();
        }

        p[0] = s;
        p[1] = t;
        p[2] = a;
        p[3] = b;
        p[4] = c;

        for (int i = 0; i < d.Length; i++) d[i] = 1e10;

        Go(0, 0);

        return d[1];
    }

    private static Point[] p = new Point[5];
    private static double[] d = new double[5];
    private static void Go(int pos, double dist)
    {
        if (d[pos] < dist) return;
        d[pos] = dist;
        if (pos == 1) return;

    }

    private static void Main(string[] args)
    {/*
        PushTestData(@"
1
0 0 0 10 -10 20 0 1 10 20
0 0 0 10 -10 20 1 1 10 20
0 0 0 10 -10 20 -1 1 10 20

0 0 0 10 -10 1 0 1 10 1
0 0 0 10 -10 1 1 1 10 1
0 0 0 10 -10 1 -1 1 10 1

");

        int n = ReadInt();
        double[] answer = new double[n];
        for (int i = 0; i < n; i++)
        {
            var s = ReadPoint();
            var t = ReadPoint();
            var a = ReadPoint();
            var b = ReadPoint();
            var c = ReadPoint();

            answer[i] = Solve(s, t, a, b, c);
        }

        Console.WriteLine(string.Join(Environment.NewLine, answer));*/

        int n = ReadInt();
        int[] a = ReadIntArray(n);

        var stMax = new SegmentTree<int>(0, n, Math.Max);
        var stMin = new SegmentTree<int>(int.MaxValue, n, Math.Min);

        int[] m = new int[n];
        Array.Copy(a, m, n);
        Array.Sort(m);
        Dictionary<int, int> pos = new Dictionary<int, int>();
        Dictionary<int, int> pos2 = new Dictionary<int, int>();
        for (int i = 0; i < n; i++) pos.Add(m[i], i);
        for (int i = 0; i < n; i++) pos2.Add(a[i], i);

        int[] ans = new int[n - 1];
        for (int i = 0; i < n; i++)
        {
            int ps = pos[a[i]];

            if (i > 0)
            {
                int mn = stMin.Get(ps, n - 1);
                int mx = stMax.Get(0, ps);

                if (mn == int.MaxValue) mn = 0;

                if (mn == 0 || mx == 0)
                    ans[i - 1] = mx + mn;
                else
                {
                    int ps1 = pos2[mn];
                    int ps2 = pos2[mx];
                    if (ps1 > ps2)
                        ans[i - 1] = mn;
                    else
                        ans[i - 1] = mx;
                }

            }

            stMin.Update(ps, a[i]);
            stMax.Update(ps, a[i]);
        }

        Console.Write(string.Join(" ", ans));
    }

    public class SegmentTree<T> where T : IComparable<T>
    {
        private int Mid;
        private T[] t;
        private Func<T, T, T> f;
        private T defValue = default(T);

        public SegmentTree(T[] a, Func<T, T, T> f, T defValue)
        {
            this.Mid = 1;
            while (Mid < a.Length) Mid *= 2;
            this.t = new T[Mid + Mid];
            this.f = f;

            Array.Copy(a, 0, this.t, Mid, a.Length);
            for (int i = (Mid + a.Length - 1) / 2; i > 0; i--) this.UpdateValueFor(i);
        }

        public SegmentTree(T defValue, int capacity, Func<T, T, T> f)
        {
            this.defValue = defValue;
            this.Mid = 1;
            while (Mid < capacity) Mid *= 2;
            this.t = new T[Mid + Mid];
            this.f = f;

            for (int i = 0; i < Mid; i++)
                this.t[Mid + i] = defValue;

            for (int i = (Mid + Mid - 1) / 2; i > 0; i--) this.UpdateValueFor(i);
        }

        public T GetRoot()
        {
            return t[1];
        }

        public T Get(int l, int r)
        {
            l += Mid;
            r += Mid;

            T ans = this.defValue;
            while (l <= r)
            {
                if ((l & 1) == 1) ans = this.f(ans, t[l]);
                if ((r & 1) == 0) ans = this.f(ans, t[r]);

                l = (l + 1) >> 1;
                r = (r - 1) >> 1;
            }

            return ans;
        }

        public void Update(int i, T value)
        {
            t[i + Mid] = value;
            for (i = (i + Mid) >> 1; i >= 1; i = (i >> 1)) this.UpdateValueFor(i);
        }

        private void UpdateValueFor(int i)
        {
            t[i] = this.f(t[i + i], t[i + i + 1]);
        }
    }

    private static List<int>[] ReadGraph(int n, int m)
    {
        List<int>[] g = new List<int>[n];
        for (int i = 0; i < n; i++) g[i] = new List<int>();
        for (int i = 0; i < m; i++)
        {
            int a = ReadInt() - 1;
            int b = ReadInt() - 1;

            g[a].Add(b);
            g[b].Add(a);
        }

        return g;
    }

    private static int[,] ReadGraphAsMatrix(int n, int m)
    {
        int[,] matrix = new int[n + 1, n + 1];
        for (int i = 0; i < m; i++)
        {
            int a = ReadInt();
            int b = ReadInt();
            matrix[a, b] = matrix[b, a] = 1;
        }

        return matrix;
    }

    private static void Sort(ref int a, ref int b)
    {
        if (a > b) Swap(ref a, ref b);
    }

    private static void Swap(ref int a, ref int b)
    {
        int tmp = a;
        a = b;
        b = tmp;
    }

    private const int BufferSize = 1 << 16;
    private static StreamReader consoleReader;
    private static MemoryStream testData;

    private static int ReadInt()
    {
        int ans = 0;
        int mul = 1;
        do
        {
            ans = consoleReader.Read();
            if (ans == -1)
                return 0;
            if (ans == '-') mul = -1;
        } while (ans < '0' || ans > '9');

        ans -= '0';
        while (true)
        {
            int chr = consoleReader.Read();
            if (chr < '0' || chr > '9')
                return ans * mul;
            ans = ans * 10 + chr - '0';
        }
    }

    private static ulong ReadULong()
    {
        ulong ans = 0;
        int chr;
        do
        {
            chr = consoleReader.Read();
            if (chr == -1)
                return 0;
        } while (chr < '0' || chr > '9');

        ans = (uint)(chr - '0');
        while (true)
        {
            chr = consoleReader.Read();
            if (chr < '0' || chr > '9')
                return ans;
            ans = ans * 10 + (uint)(chr - '0');
        }
    }

    private static long ReadLong()
    {
        long ans = 0;
        int mul = 1;
        do
        {
            ans = consoleReader.Read();
            if (ans == -1)
                return 0;
            if (ans == '-') mul = -1;
        } while (ans < '0' || ans > '9');

        ans -= '0';
        while (true)
        {
            int chr = consoleReader.Read();
            if (chr < '0' || chr > '9')
                return ans * mul;
            ans = ans * 10 + chr - '0';
        }
    }

    private static int[] ReadIntArray(int n)
    {
        int[] ans = new int[n];
        for (int i = 0; i < n; i++)
            ans[i] = ReadInt();
        return ans;
    }

    private static long[] ReadLongArray(int n)
    {
        long[] ans = new long[n];
        for (int i = 0; i < n; i++)
            ans[i] = ReadLong();
        return ans;
    }

    private static char[] ReadString()
    {
        int ans;

        do
        {
            ans = consoleReader.Read();
        } while (!((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z')));

        List<char> s = new List<char>();
        do
        {
            s.Add((char)ans);
            ans = consoleReader.Read();
        } while ((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z'));

        return s.ToArray();
    }

    private static char[] ReadString(int n)
    {
        int ans;

        do
        {
            ans = consoleReader.Read();
        } while (!((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z')));

        char[] s = new char[n];
        int pos = 0;
        do
        {
            s[pos++] = (char)ans;
            if (pos == n) break;
            ans = consoleReader.Read();
        } while ((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z'));

        return s;
    }

    private static char ReadLetter()
    {
        while (true)
        {
            int ans = consoleReader.Read();
            if ((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z'))
                return (char)ans;
        }
    }

    private static char ReadDigit()
    {
        while (true)
        {
            int ans = consoleReader.Read();
            if (ans >= '0' && ans <= '9')
                return (char)ans;
        }
    }

    private static int ReadDigitInt()
    {
        return ReadDigit() - (int)'0';
    }

    private static char ReadAnyChar()
    {
        return (char)consoleReader.Read();
    }

    private static string DoubleToString(double x)
    {
        return x.ToString(CultureInfo.InvariantCulture);
    }

    static Program()
    {
        //Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
        consoleReader = new StreamReader(Console.OpenStandardInput(BufferSize), Encoding.ASCII, false, BufferSize);
    }

    private static void PushTestData(string data)
    {
#if !ONLINE_JUDGE
        if (testData == null)
        {
            testData = new MemoryStream();
            consoleReader = new StreamReader(testData);
        }

        var pos = testData.Position;
        var bytes = Encoding.UTF8.GetBytes(data);
        testData.Write(bytes, 0, bytes.Length);
        testData.Flush();
        testData.Position = pos;
#endif
    }
}


#include <stdio.h>

#define MAX 100000

unsigned long int n,i;
unsigned long int x[MAX+1];
unsigned long int p[MAX+1];
unsigned long int l[MAX+1];
unsigned long int r[MAX+1];

void build() {
  unsigned long int pa, lastpa;
  for(i=1; i<=n; i++){
	p[i]=0; l[i]=0; r[i]=0;
  }

  for (i=2; i<=n; i++ ){
     pa=1;
     while (pa!=0) {
	lastpa=pa;
        if (x[i]<x[pa]) pa=l[pa]; else pa=r[pa];
     }
     p[i]=lastpa;
     if (x[i]<x[lastpa])  l[lastpa]=i; else r[lastpa]=i;
  }
}

void inp() {
  scanf("%ld", &n);
  i=1;
  while (i<=n) {
	scanf("%ld", &x[i]);
	i++;
  }
}

void op() {
  char ch=0;
  for (i=2; i<=n; i++ ) {
	if (ch!=0) printf("%c",ch);
	printf("%ld", x[p[i]]);
	ch=' ';
  }
}
int main() {
  inp();
  build();
  op();
  return 0;
}


#include <stdio.h>
#include <time.h>
#include <stdlib.h>

#define MAX 100100

int n,i,j;

int x[MAX];
int p[MAX];
int s[MAX];
int t[MAX];
int xx[MAX];

struct node {
  int   low, high, value;
  int   left, right, parent, height;
};

struct node nd[MAX];
int root=0, avail=0;

#define nd_height(i) ((i) ? nd[i].height : -1)

void avl_update(int p) {
  nd[p].height=
   (nd_height(nd[p].left) > nd_height(nd[p].right))
	? nd_height(nd[p].left)+1:nd_height(nd[p].right)+1;
}

void avl_rotate_l(int i) {
  int j, pi, lj;
//  printf("R L\n");
  j=nd[i].right;
  pi=nd[i].parent;
  lj=nd[j].left;

  nd[j].left=i; nd[i].parent=j;
  nd[j].parent= pi; nd[i].right=lj;

  if (lj) nd[lj].parent =i;
  if (pi) {
    if (nd[pi].left==i) nd[pi].left=j; else nd[pi].right=j;
  } else root=j;

  avl_update(i);
  avl_update(j);
}

void avl_rotate_r(int i) {
  int j, pi, rj;
//  printf("R R\n");
  j=nd[i].left;
  pi=nd[i].parent;
  rj=nd[j].right;

  nd[j].right=i;
  nd[i].parent=j;
  nd[j].parent=pi;
  nd[i].left= rj;

  if (rj) nd[rj].parent =i;
  if (pi) {
    if (nd[pi].left==i) nd[pi].left=j; else nd[pi].right=j;
  }else root=j;
  avl_update(i);
  avl_update(j);
}

void avl_balance(int i){ // i is inserted node
   int p=nd[i].parent, lp=0;
//  printf("BAL\n");
   while (p) {
	nd[p].height=
	   (nd_height(nd[p].left) > nd_height(nd[p].right))
		? nd_height(nd[p].left)+1:nd_height(nd[p].right)+1;
	if (abs(nd_height(nd[p].left)-nd_height(nd[p].right)) > 1) { //unbalanced condition
		if (nd[p].left==lp) {
		   if (nd[i].low< nd[lp].low) { //LL
			avl_rotate_r(p);
		   } else {			//LR
			avl_rotate_l(lp);
			avl_rotate_r(p);
		   }
		} else {
		   if (nd[i].low< nd[lp].low) { //RL
			avl_rotate_r(lp);
			avl_rotate_l(p);
		   } else {			//RR
			avl_rotate_l(p);
		   }
		}
	} else {
             lp=p; p=nd[p].parent;
	}
   }
}

void avl_insert(int i) {
  int p, lp;
  nd[i].left=nd[i].right=0;
  if (root==0) {root=i; nd[i].parent=0; nd[i].height=0; return ; }

  p=root;
  while (p) {
    lp=p;
    if ( nd[i].low < nd[p].low ) p=nd[p].left; else p=nd[p].right;
  }
//  printf("\nlp=%d\n", lp);
  nd[i].parent=lp;
  nd[i].height =0; // leaf node's height is 0
  if ( nd[i].low < nd[lp].low ) nd[lp].left=i; else nd[lp].right=i;

  avl_balance(i);
}

void avl_show() {
   int h=0;
   int p=root;
   printf("\nroot=%d", root);
   for(j=1; j<=i; j++) {
      printf("\n%d-->%d, par=%d, left=%d, right=%d", j,nd[j].low, nd[j].parent, nd[j].left, nd[j].right);
   }
   printf("\n\n");
}

void avl_node(int l, int h, int v) {
   if (l>h) return ;
//   printf("\nl=%d,h=%d, v=%d\n", l,h,v);

   avail++;
   nd[avail].low=l;
   nd[avail].high=h;
   nd[avail].value=v;
   avl_insert(avail);
}

int avl_find(int   o) {
  int p=root;
  while (p) {
     if (o < nd[p].low) p=nd[p].left;
     else
     if (o > nd[p].high) p=nd[p].right;
     else return p; // found o in p
  }
  return 0;
}

unsigned int c[10];
void sort() {
  int k,kk,z;
  for(i=1; i<=n; i++) s[i]=i;
  k=10; kk=1;
  for(i=1; i<=9; i++) {
	for(z=0; z<10; z++) c[z]=0;
	for (j=1; j<=n; j++) {
            c[(x[s[j]]%k)/kk]++;
	}
	for(z=1; z<10; z++) c[z]=c[z]+c[z-1];

	for (j=n; j>=1; j--) {
	   z=(x[s[j]]%k)/kk;
	   t[c[z]]=s[j];
	   xx[s[j]]=c[z];
	   c[z]--;
	}

	for(j=1; j<=n; j++) s[j]=t[j];
        k*=10; kk*=10;
  }
}

void op() {
	j=2;
	while (j<=n) {
		printf("%d ",p[j]);
		j++;
	}
}

void inp() {
  char ch=0;
  scanf("%d", &n);

  i=1;
  while (i<=n) {
	scanf("%d", &x[i]);
	i++;
  }
}

void compute() {
  int ix,jx,e,f;
//  for(i=1; i<=n; i++) p[i]=0;
  p[1]=0;
  ix=xx[1];
  avl_node(1,ix-1, x[1]);
  avl_node(ix+1,n, x[1]);

  for (i=2; i<=n; i++ ){
	ix=xx[i];
	jx=avl_find(ix);
	if (jx) {
	    p[i]= nd[jx].value;

	    e=nd[jx].low; f=nd[jx].high;
	    nd[jx].low=nd[jx].high= ix;
	    avl_node(e,ix-1, x[i]);
	    avl_node(ix+1,f, x[i]);
	} else {
	   fprintf(stderr, "Erorr");
	   exit(1);
	}
  }
}

int main() {
  clock_t t1=clock();

  inp();
  sort();
  compute();
  op();

  clock_t t2=clock();
  fprintf(stderr, "\nn=%d, time=%ld,%ld, %ld\n",n, t1,t2, t2-t1);

  return 0;
}

//testing avl
int main2() {
 int d;
  i=0;
  printf("Enter d : ");
  scanf("%d", &d);
  nd[++i].low=d;
  while (d) {
	avl_insert(i);
	avl_show();

	printf("Enter d : ");
	scanf("%d", &d);
	nd[++i].low=d;
  }
  return 0;
}


#include <stdio.h>

#define MAX 100000
#define LL 999999999
#define co(i) s[(i)]+1

unsigned long int n,i,j;
unsigned long int x[MAX+1];
unsigned long int s[MAX+1];
unsigned long int p[MAX+1];

void build2() {
  unsigned long int ix,jx;
  for(i=1; i<=n; i++) p[i]=0;

  for (i=1; i<=n; i++ ){
     ix=co(i);
     jx=ix+1;
     while (jx<=n && p[jx]==p[ix]) p[jx++]=i;
     jx=ix-1;
     while (jx>=1 && p[jx]==p[ix]) p[jx--]=i;
  }
}

void compute() {
  register unsigned long int cc;
  for(i=1; i<=n ; i++ ) {
     cc=0;
     for(j=1; j<=n; j++){
       if (x[j]<x[i]) cc++;
     }
     s[i]=cc;
  }
}

void inp() {
  scanf("%ld", &n);
  i=1;
  while (i<=n) {
	scanf("%ld", &x[i]);
	i++;
  }
}

void op() {
  char ch=0;
  for (i=2; i<=n; i++ ) {
	if (ch!=0) printf("%c",ch);
	printf("%ld", x[p[co(i)]]);
	ch=' ';
  }
}

int main() {
  inp();
  compute();
  build2();
  op();
  return 0;
}

/*
   1 2 3 4 5 6 7 8 9
x  5 3 8 4 2 9

   1 2 3 4 5 6 7 8 9
co 0 1 1 1 1 0 0 1 1
   0 1 2 3 4 4 4 5 6

   1 2 3 4 5 6
p  2 1 2 0 1 3

*/


#include <stdio.h>
#include <time.h>
#include <stdlib.h>

#define MAX 100100

int n,i,j;

int x[MAX];
int p[MAX];
int s[MAX];
int t[MAX];
int xx[MAX];

struct node {
  int   low, high, value;
  int   left, right, parent, height;
  float mid;
  float r;
};

struct node nd[MAX];
int root=0, avail=0;

#define nd_height(i) ((i) ? nd[i].height : -1)

void avl_update(int p) {
  nd[p].height=
   (nd_height(nd[p].left) > nd_height(nd[p].right))
	? nd_height(nd[p].left)+1:nd_height(nd[p].right)+1;
}

void avl_rotate_l(int i) {
  int j, pi, lj;
//  printf("R L\n");
  j=nd[i].right;
  pi=nd[i].parent;
  lj=nd[j].left;

  nd[j].left=i; nd[i].parent=j;
  nd[j].parent= pi; nd[i].right=lj;

  if (lj) nd[lj].parent =i;
  if (pi) {
    if (nd[pi].left==i) nd[pi].left=j; else nd[pi].right=j;
  } else root=j;

  avl_update(i);
  avl_update(j);
}

void avl_rotate_r(int i) {
  int j, pi, rj;
//  printf("R R\n");
  j=nd[i].left;
  pi=nd[i].parent;
  rj=nd[j].right;

  nd[j].right=i;
  nd[i].parent=j;
  nd[j].parent=pi;
  nd[i].left= rj;

  if (rj) nd[rj].parent =i;
  if (pi) {
    if (nd[pi].left==i) nd[pi].left=j; else nd[pi].right=j;
  }else root=j;
  avl_update(i);
  avl_update(j);
}

void avl_balance(int i){ // i is inserted node
   int p=nd[i].parent, lp=0;
//  printf("BAL\n");
   while (p) {
	nd[p].height=
	   (nd_height(nd[p].left) > nd_height(nd[p].right))
		? nd_height(nd[p].left)+1:nd_height(nd[p].right)+1;
	if (abs(nd_height(nd[p].left)-nd_height(nd[p].right)) > 1) { //unbalanced condition
		if (nd[p].left==lp) {
		   if (nd[i].low< nd[lp].low) { //LL
			avl_rotate_r(p);
		   } else {			//LR
			avl_rotate_l(lp);
			avl_rotate_r(p);
		   }
		} else {
		   if (nd[i].low< nd[lp].low) { //RL
			avl_rotate_r(lp);
			avl_rotate_l(p);
		   } else {			//RR
			avl_rotate_l(p);
		   }
		}
	} else {
             lp=p; p=nd[p].parent;
	}
   }
}

void avl_insert(int i) {
  int p, lp;
  nd[i].left=nd[i].right=0;
  if (root==0) {root=i; nd[i].parent=0; nd[i].height=0; return ; }

  p=root;
  while (p) {
    lp=p;
    if ( nd[i].low < nd[p].low ) p=nd[p].left; else p=nd[p].right;
  }
//  printf("\nlp=%d\n", lp);
  nd[i].parent=lp;
  nd[i].height =0; // leaf node's height is 0
  if ( nd[i].low < nd[lp].low ) nd[lp].left=i; else nd[lp].right=i;

  avl_balance(i);
}

void avl_show() {
   int h=0;
   int p=root;
   printf("\nroot=%d", root);
   for(j=1; j<=i; j++) {
      printf("\n%d-->%d, par=%d, left=%d, right=%d", j,nd[j].low, nd[j].parent, nd[j].left, nd[j].right);
   }
   printf("\n\n");
}

void avl_node(int l, int h, int v) {
   if (l>h) return ;
//   printf("\nl=%d,h=%d, v=%d\n", l,h,v);

   avail++;
   nd[avail].low=l;
   nd[avail].high=h;
   nd[avail].value=v;
   avl_insert(avail);
}

int avl_find(int   o) {
  int p=root;
  while (p) {
     if (o < nd[p].low) p=nd[p].left;
     else
     if (o > nd[p].high) p=nd[p].right;
     else return p; // found o in p
  }
  return 0;
}

unsigned int c[10];
void sort() {
  int k,kk,z;
  for(i=1; i<=n; i++) s[i]=i;
  k=10; kk=1;
  for(i=1; i<=9; i++) {
	for(z=0; z<10; z++) c[z]=0;
	for (j=1; j<=n; j++) {
            c[(x[s[j]]%k)/kk]++;
	}
	for(z=1; z<10; z++) c[z]=c[z]+c[z-1];

	for (j=n; j>=1; j--) {
	   z=(x[s[j]]%k)/kk;
	   t[c[z]]=s[j];
	   xx[s[j]]=c[z];
	   c[z]--;
	}

	for(j=1; j<=n; j++) s[j]=t[j];
        k*=10; kk*=10;
  }
}

void op() {
	j=2;
	while (j<=n) {
		printf("%d ",p[j]);
		j++;
	}
}

void inp() {
  char ch=0;
  scanf("%d", &n);

  i=1;
  while (i<=n) {
	scanf("%d", &x[i]);
	i++;
  }
}

void compute() {
  int ix,jx,e,f;
//  for(i=1; i<=n; i++) p[i]=0;
  p[1]=0;
  ix=xx[1];
  avl_node(1,ix-1, x[1]);
  avl_node(ix+1,n, x[1]);

  for (i=2; i<=n; i++ ){
	ix=xx[i];
	jx=avl_find(ix);
	if (jx) {
	    p[i]= nd[jx].value;

	    e=nd[jx].low; f=nd[jx].high;
	    nd[jx].low=nd[jx].high= ix;
	    avl_node(e,ix-1, x[i]);
	    avl_node(ix+1,f, x[i]);
	} else {
	   fprintf(stderr, "Erorr");
	   exit(1);
	}
  }
}

int main() {
  clock_t t1=clock();

  inp();
  sort();
  compute();
  op();

  clock_t t2=clock();
  fprintf(stderr, "\nn=%d, time=%ld,%ld, %ld\n",n, t1,t2, t2-t1);

  return 0;
}

int main2() {
 int d;
  i=0;
  printf("Enter d : ");
  scanf("%d", &d);
  nd[++i].low=d;
  while (d) {
	avl_insert(i);
	avl_show();

	printf("Enter d : ");
	scanf("%d", &d);
	nd[++i].low=d;
  }
  return 0;
}


#include <stdio.h>

#define MAX 100000

unsigned long int n,i;
unsigned long int x[MAX+1];
unsigned long int p[MAX+1];
unsigned long int l[MAX+1];
unsigned long int r[MAX+1];
unsigned long int s[MAX+1];
unsigned long int co[MAX+1];
unsigned long int ix[MAX+1];

void build() {
  unsigned long int pa, lastpa;
  for(i=1; i<=n; i++){
	p[i]=0; l[i]=0; r[i]=0;
  }

  for (i=2; i<=n; i++ ){
     pa=1;
     while (pa!=0) {
	lastpa=pa;
        if (x[i]<x[pa]) pa=l[pa]; else pa=r[pa];
     }
     p[i]=lastpa;
     if (x[i]<x[lastpa])  l[lastpa]=i; else r[lastpa]=i;
  }
}

void build2() {
  unsigned long int ix,jx;
  for(i=1; i<=n; i++) p[i]=0;

  for (i=1; i<=n; i++ ){
     ix=co[ x[i] ];
     jx=ix+1;
     while (jx<=n && p[jx]==p[ix]) p[jx++]=i;
     jx=ix-1;
     while (jx>=1 && p[jx]==p[ix]) p[jx--]=i;
  }
}

void sort() {
// counting sort only calculate co
   for(i=1; i<=n; i++) s[i]=i;
   for(i=2; i<=MAX;i++) co[i]=co[i]+co[i-1];
}

void inp() {
  scanf("%ld", &n);

  for(i=1; i<=MAX; i++) co[i]=0;
  i=1;
  while (i<=n) {
	scanf("%ld", &x[i]);
	co[x[i]]=1;
	i++;
  }
}

void op() {
  char ch=0;
  for (i=2; i<=n; i++ ) {
	if (ch!=0) printf("%c",ch);
	printf("%ld", x[p[co[x[i]]]]);
	ch=' ';
  }
}
int main() {
  inp();
  sort();
  build2();
  op();
  return 0;
}

/*
   1 2 3 4 5 6
x  5 3 8 4 2 9

   1 2 3 4 5 6 7 8 9
co 0 1 1 1 1 0 0 1 1
   0 1 2 3 4 4 4 5 6

   1 2 3 4 5 6
s

   1 2 3 4 5 6
p  2 1 2 0 1 3

*/


#include <stdio.h>

#define MAX 100000
#define LL 99999999
#define co(i) s[(i)]+1

unsigned long int n,i,j;
unsigned long int x[MAX+1];
unsigned long int s[MAX+1];
unsigned long int p[MAX+1];
char f[LL];

void build2() {
  unsigned long int ix,jx;
  for(i=1; i<=n; i++) p[i]=0;

  for (i=1; i<=n; i++ ){
     ix=co(i);
     jx=ix+1;
     while (jx<=n && p[jx]==p[ix]) p[jx++]=i;
     jx=ix-1;
     while (jx>=1 && p[jx]==p[ix]) p[jx--]=i;
  }
}

void compute() {
  for(i=1; i<=n ; i++ ) s[i]=0;

  for(i=1; i<=n ; i++ ) {
     for(j=i+1; j<=n; j++){
       if (x[j]<x[i]) s[i]++; else s[j]++;
     }
  }
}

void inp() {
  scanf("%ld", &n);

//  for(i=0; i<LL ; i++ ) f[i]=0;
  i=1;
  while (i<=n) {
	scanf("%ld", &x[i]);
//	f[x[i]]=1;
	i++;
  }
}

void op() {
  char ch=0;
  for (i=2; i<=n; i++ ) {
	if (ch!=0) printf("%c",ch);
	printf("%ld", x[p[co(i)]]);
	ch=' ';
  }
}

int main() {
  inp();
  compute();
  build2();
  op();
  return 0;
}

/*
   1 2 3 4 5 6 7 8 9
x  5 3 8 4 2 9

   1 2 3 4 5 6 7 8 9
co 0 1 1 1 1 0 0 1 1
   0 1 2 3 4 4 4 5 6

   1 2 3 4 5 6
p  2 1 2 0 1 3

*/


#include <stdio.h>

#define MAX 100000
#define LL 999999999
#define co(i) s[(i)]+1

unsigned long int n,i,j;
unsigned long int x[MAX+1];
unsigned long int s[MAX+1];
unsigned long int p[MAX+1];

void build2() {
  unsigned long int ix,jx;
  for(i=1; i<=n; i++) p[i]=0;

  for (i=1; i<=n; i++ ){
     ix=co(i);
  //   printf ("x=%ld ix=%ld\n", x[i], ix);
     jx=ix+1;
     while (jx<=n && p[jx]==p[ix]) p[jx++]=i;
     jx=ix-1;
     while (jx>=1 && p[jx]==p[ix]) p[jx--]=i;
  }
}

void compute() {
  for(i=1; i<=n ; i++ ) {
	s[i]=0;
	for(j=1; j<=n; j++){
  	  if (x[j]<x[i]) s[i]++;
	}
  }
}

void inp() {
  scanf("%ld", &n);

  i=1;
  while (i<=n) {
	scanf("%ld", &x[i]);
	i++;
  }
}

void op() {
  char ch=0;
  for (i=2; i<=n; i++ ) {
	if (ch!=0) printf("%c",ch);
	printf("%ld", x[p[co(i)]]);
	ch=' ';
  }
}
int main() {
  inp();
  compute();
  build2();
  op();
  return 0;
}

/*
   1 2 3 4 5 6 7 8 9
x  5 3 8 4 2 9

   1 2 3 4 5 6 7 8 9
co 0 1 1 1 1 0 0 1 1
   0 1 2 3 4 4 4 5 6

   1 2 3 4 5 6
p  2 1 2 0 1 3

*/


#include <stdio.h>
#include <time.h>

#define MAX 100000

unsigned long int n,i;
unsigned long int x[MAX+1];
unsigned long int p[MAX+1];
unsigned long int l[MAX+1];
unsigned long int r[MAX+1];
//unsigned long int co[MAX+1];
//unsigned long int ix[MAX+1];

void build() {
  unsigned long int pa, lastpa;
     pa=1;
     while (pa!=0) {
	lastpa=pa;
        if (x[i]<x[pa]) pa=l[pa]; else pa=r[pa];
     }
     p[i]=lastpa; l[i]=r[i]=0;
     if (x[i]<x[lastpa])  l[lastpa]=i; else r[lastpa]=i;
}

void inp() {
  char ch=0;
  scanf("%ld", &n);

  i=1;
  scanf("%ld", &x[i]);
  i++;
  l[1]=r[1]=p[1]=0;

  while (i<=n) {
	scanf("%ld", &x[i]);
	build();
//	if (ch) putchar(ch); else ch=' ';
	printf("%ld ",x[p[i]]);
	i++;
  }
}

int main() {
  clock_t t1=clock();

  inp();

  clock_t t2=clock();
  fprintf(stderr, "\nn=%ld, time=%ld,%ld, %ld\n",n, t1,t2, t2-t1);

  return 0;
}


#include <stdio.h>

#define MAX 100000
#define LL 999999999
#define co(i) s[(i)]+1

unsigned long int n,i,j;
unsigned long int x[MAX+1];
unsigned long int s[MAX+1];
unsigned long int p[MAX+1];

void build2() {
  unsigned long int ix,jx;
  for(i=1; i<=n; i++) p[i]=0;

  for (i=1; i<=n; i++ ){
     ix=co(i);
     printf ("x=%ld ix=%ld\n", x[i], ix);
     jx=ix+1;
     while (jx<=n && p[jx]==p[ix]) p[jx++]=i;
     jx=ix-1;
     while (jx>=1 && p[jx]==p[ix]) p[jx--]=i;
  }
}

void compute() {
  for(i=1; i<=n ; i++ ) {
	s[i]=0;
	for(j=1; j<=n; j++){
  	  if (x[j]<x[i]) s[i]++;
	}
  }
}

void inp() {
  scanf("%ld", &n);

  i=1;
  while (i<=n) {
	scanf("%ld", &x[i]);
	i++;
  }
}

void op() {
  char ch=0;
  for (i=2; i<=n; i++ ) {
	if (ch!=0) printf("%c",ch);
	printf("%ld", x[p[co(i)]]);
	ch=' ';
  }
}
int main() {
  inp();
  compute();
  build2();
  op();
  return 0;
}

/*
   1 2 3 4 5 6 7 8 9
x  5 3 8 4 2 9

   1 2 3 4 5 6 7 8 9
co 0 1 1 1 1 0 0 1 1
   0 1 2 3 4 4 4 5 6

   1 2 3 4 5 6
p  2 1 2 0 1 3

*/


#include<stdio.h>
#include<stdlib.h>
typedef unsigned u;
typedef struct S{struct S*C[2];u o;}v;
v*alloc(){v*x;x=malloc(sizeof(v));x->o=-1;x->C[0]=x->C[1]=NULL;return x;}
u lo(v*x)
{if(!x)return-1;u i=-1;while(++i<2)if(x->C[i])return lo(x->C[i]);return x->o;}
u hi(v*x)
{if(!x)return-1;u i=2;while(i--)if(x->C[i])return hi(x->C[i]);return x->o;}
u los(v*x,u n,u b)
{
	if(!x)return-1;
	if(!b)return x->o;
	u r=los(x->C[(n&b)>0],n,b>>1);
	if(r==-1u&&(n&b))r=hi(x->C[0]);
	return r;
}
u his(v*x,u n,u b)
{
	if(!x)return-1;
	if(!b)return x->o;
	u r=his(x->C[(n&b)>0],n,b>>1);
	if(r==-1u&&(n&b)==0)r=lo(x->C[1]);
	return r;
}
v*ins(v*x,u n,u b,u o)
{
	if(!x)x=alloc();
	if(!b)x->o=o;
	else x->C[(n&b)>0]=ins(x->C[(n&b)>0],n,b>>1,o);
	return x;
}
u N[111111],D[111111];v*x;
int main()
{
	u n,i,j,k,l,h,z;
	scanf("%u%u",&n,N);
	x=ins(x,*N,1u<<31,0);
	for(i=0;++i<n;N[i]=k)
	{
		scanf("%u",&k);j=0;z=-1;
		l=los(x,k,1u<<31);
		h=his(x,k,1u<<31);
		if(l!=-1u&&D[l]+1>j){j=D[l]+1;z=N[l];}
		if(h!=-1u&&D[h]+1>j){j=D[h]+1;z=N[h];}
		x=ins(x,k,1u<<31,D[i]=j);
		printf("%u%c",z,i+1<n?' ':'\n');
	}
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
typedef unsigned u;
typedef struct S{struct S*C[2];u o;}v;
v*alloc(){v*x;x=malloc(sizeof(v));x->o=-1;x->C[0]=x->C[1]=NULL;return x;}
u lo(v*x)
{if(!x)return-1;u i=-1;while(++i<2)if(x->C[i])return lo(x->C[i]);return x->o;}
u hi(v*x)
{if(!x)return-1;u i=2;while(i--)if(x->C[i])return hi(x->C[i]);return x->o;}
u los(v*x,u n,u b)
{
	if(!x)return-1;
	if(!b)return x->o;
	u r=los(x->C[(n&b)>0],n,b>>1);
	if(r==-1u&&(n&b))r=hi(x->C[0]);
	return r;
}
u his(v*x,u n,u b)
{
	if(!x)return-1;
	if(!b)return x->o;
	u r=his(x->C[(n&b)>0],n,b>>1);
	if(r==-1u&&(n&b)==0)r=lo(x->C[1]);
	return r;
}
v*ins(v*x,u n,u b,u o)
{
	if(!x)x=alloc();
	if(!b)x->o=o;
	else x->C[(n&b)>0]=ins(x->C[(n&b)>0],n,b>>1,o);
	return x;
}
u N[111111],D[111111];v*x;
int main()
{
	u n,i,j,k,l,h,z;
	scanf("%u%u",&n,N);
	x=ins(x,*N,1u<<31,0);
	for(i=0;++i<n;D[i]=j,N[i]=k)
	{
		scanf("%u",&k);j=0;z=-1;
		l=los(x,k,1u<<31);
		h=his(x,k,1u<<31);
		if(l!=-1u&&D[l]+1>j){j=D[l]+1;z=N[l];}
		if(h!=-1u&&D[h]+1>j){j=D[h]+1;z=N[h];}
		x=ins(x,k,1u<<31,i);
		printf("%u\n",z);
	}
	return 0;
}


//requires stdlib.h
#include<stdio.h>
#include<stdlib.h>

typedef struct __struct_BSTV{
    int val;
}BSTV;

typedef struct __struct_BST{
    BSTV val;  //Values stored in the node.
    int h;  //Height of the node. Starts from 0 for leaf nodes
    int count;  //Count of the number 'val' present in the BST. Set to 0 if deleted
    int w;  //Number of numbers in the sub-tree rooted at this node
    struct __struct_BST *left,*right;  //left and right children
}BST;

BSTV BST_makeV(int);
int BST_cmp(BSTV, BSTV);
void BST_insert(BST **, BSTV);
void BST_update(BST **);
int BST_geth(BST *);
int BST_getw(BST *);
int BST_getc(BST *);
void BST_fixit(BST **);
void BST_rotl(BST **);
void BST_rotr(BST **);
BST * BST_search(BST *, BSTV);
void BST_delete(BST **, BSTV);
int BST_lessthan(BST *, BSTV);
int BST_greaterthan(BST *, BSTV);
BST *BST_previous(BST *, BSTV);
BST *BST_next(BST *, BSTV);

int main(){
	BST *all, *left, *right, *tmp;
	int n,i,j;
	all=left=right=NULL;
	scanf("%d", &n);
	while(n--){
		scanf("%d", &i);
		tmp=BST_previous(all, BST_makeV(i));
		BST_insert(&all, BST_makeV(i));
		if(tmp!=NULL && BST_search(right, tmp->val)==NULL){
			printf("%d ", tmp->val.val);
			BST_insert(&right, tmp->val);
		}
		else if((tmp=BST_next(all, BST_makeV(i)))!=NULL && BST_search(left, tmp->val)==NULL){
			printf("%d ", tmp->val.val);
			BST_insert(&left, tmp->val);
		}
	}
	printf("\n");
	return 0;
}

BSTV BST_makeV(int val){
    /*
      returns the struct which is used by the bst
    */
    BSTV retval;
    retval.val = val;
    return retval;
}

int BST_cmp(BSTV a, BSTV b){
    /*
      Compares the values of a and b
      -1(less than zero) if a < b
      0 if a == b
      1(greater than zero) if a > b
    */
    return a.val - b.val;
}

void BST_insert(BST **tarp, BSTV val){
    /*
      Inserts the number 'val' under the BST whose pointer is pointed by tarp
    */
    BST *target = *tarp;
    if(target == NULL){
	//Make a new leaf node
	target = (BST *)malloc(sizeof(BST));
	target->val = val;
	target->h = 0;
	target->left = NULL;
	target->right = NULL;
	target->count = 1;
	target->w = 1;
	*tarp = target;  //Change the pointer value to the newly allocated node
	return ;
    }
    if(BST_cmp(target->val, val) == 0){
	//Number already present in the BST. Only need to increase the count.
	target->count++;
	target->w++;
    }
    else if(BST_cmp(target->val, val) > 0){
	BST_insert(&(target->left), val);
    }
    else{
	BST_insert(&(target->right), val);
    }
    //Update values like height, weight etc.
    BST_update(tarp);
}

void BST_update(BST **tarp){
    /*
      Updates 'w' and 'h' of the BST.
      Make sure the children are updated before calling this for the parent.
    */
    BST *target = *tarp;
    int lh, rh;
    if(target == NULL){
	return ;
    }
    target->w = BST_getw(target->left) + BST_getw(target->right) + target->count;
    lh = BST_geth(target->left);
    rh = BST_geth(target->right);
    if(lh > rh)
	target->h = lh+1;
    else
	target->h = rh+1;
    //Make sure the BST is balanced
    if(lh > rh+1 || rh > lh+1)
	BST_fixit(tarp);
}

int BST_getw(BST *target){
    if(target == NULL)
	return 0;
    return target->w;
}

int BST_geth(BST *target){
    //Set height of NULL to -1 to make height of leaf nodes as 0
    if(target == NULL)
	return -1;
    return target->h;
}

int BST_getc(BST *target){
    if(target == NULL)
	return 0;
    return target->count;
}

void BST_fixit(BST **tarp){
    /*
      Fixes imbalanced BST
    */
    BST *target = *tarp;
    if(BST_geth(target->left) > BST_geth(target->right)){
	if(BST_geth(target->left->left) > BST_geth(target->left->right)){
	    BST_rotr(tarp);
	    BST_update(&((*tarp)->right));
	    BST_update(tarp);
	}
	else{
	    BST_rotl(&(target->left));
	    BST_rotr(tarp);
	    target = *tarp;
	    BST_update(&(target->left));
	    BST_update(&(target->right));
	    BST_update(tarp);
	}
    }
    else{
	if(BST_geth(target->right->right) > BST_geth(target->right->left)){
	    BST_rotl(tarp);
	    BST_update(&((*tarp)->left));
	    BST_update(tarp);
	}
	else{
	    BST_rotr(&(target->right));
	    BST_rotl(tarp);
	    target = *tarp;
	    BST_update(&(target->right));
	    BST_update(&(target->left));
	    BST_update(tarp);
	}
    }
}

void BST_rotl(BST **tarp){
    /*
      Rotates the node towards left ie. CCW
    */
    BST *r, *target;
    target = *tarp;
    r = target->right;
    *tarp = r;
    target->right = r->left;
    r->left = target;
}

void BST_rotr(BST **tarp){
    /*
      Rotates the node towards left ie. CCW
    */
    BST *l, *target;
    target = *tarp;
    l = target->left;
    *tarp = l;
    target->left = l->right;
    l->right = target;
}

BST *BST_search(BST *target, BSTV val){
    /*
      Search for the node containing the number 'val'
    */
    if(target == NULL)
	return NULL;
    if(BST_cmp(target->val, val) == 0)
	return target;
    else if(BST_cmp(target->val, val) > 0){
	return BST_search(target->left, val);
    }
    else{
	return BST_search(target->right, val);
    }
}

void BST_delete(BST **tarp, BSTV val){
    /*
      Delete the number 'val' from the BST
    */
    BST *target;
    if(tarp == NULL)
	return ;
    target = *tarp;
    if(BST_cmp(target->val, val) == 0){
	if(target->count > 0){
	    target->count--;
	    target->w--;
	}
    }
    else if(BST_cmp(target->val, val) > 0){
	BST_insert(&(target->left), val);
    }
    else{
	BST_insert(&(target->right), val);
    }
    BST_update(tarp);
}

int BST_lessthan(BST *target, BSTV val){
    /*
      Return the number of elements in the BST lesser than 'val'
    */
    if(target == NULL)
	return 0;
    if(BST_cmp(target->val, val) >= 0){
	return BST_lessthan(target->left, val);
    }
    else{
	return BST_lessthan(target->right, val) + BST_getc(target) + BST_getw(target->left);
    }
}

int BST_greaterthan(BST *target, BSTV val){
    /*
      Return the number of elements in the BST greater than 'val'
    */
    if(target == NULL)
	return 0;
    if(BST_cmp(target->val, val) <= 0){
	return BST_greaterthan(target->right, val);
    }
    else{
	return BST_greaterthan(target->left, val) + BST_getc(target) + BST_getw(target->right);
    }
}

BST *BST_previous(BST *node, BSTV val){
    /*
      Return the node which comes before 'val' in-order.
      Returns NULL if no node is found.
    */
    if(node == NULL)
	return NULL;
    if(BST_cmp(node->val, val) < 0){
	BST *tmp = BST_previous(node->right, val);
	if(tmp)
	    return tmp;
	if(BST_getc(node)){
	    return node;
	}
    }
    return BST_previous(node->left, val);
}

BST *BST_next(BST *node, BSTV val){
    /*
      Return the node which comes after 'val' in-order.
      Returns NULL if no node is found.
    */
    if(node == NULL)
	return NULL;
    if(BST_cmp(node->val, val) > 0){
	BST *tmp = BST_next(node->left, val);
	if(tmp)
	    return tmp;
	if(BST_getc(node)){
	    return node;
	}
    }
    return BST_next(node->right, val);
}


#include<stdio.h>
#include<stdlib.h>

typedef struct __struct_BST{
	int val;  //Values stored in the node.
	int h;  //Height of the node. Starts from 0 for leaf nodes
	int count;  //Count of the number 'val' present in the BST. Set to 0 if deleted
	int w;  //Number of numbers in the sub-tree rooted at this node
	struct __struct_BST *left,*right;  //left and right children
}BST;

void BST_insert(BST **, int);
void BST_update(BST **);
int BST_geth(BST *);
int BST_getw(BST *);
int BST_getc(BST *);
void BST_fixit(BST **);
void BST_rotl(BST **);
void BST_rotr(BST **);
BST * BST_search(BST *, int);
void BST_delete(BST **, int);
int BST_lessthan(BST *, int);
int BST_greaterthan(BST *, int);
BST *BST_previous(BST *, int);
BST *BST_next(BST *, int);

int main(){
	BST *all, *left, *right, *tmp;
	int n,i,j;
	all=left=right=NULL;
	scanf("%d", &n);
	while(n--){
		scanf("%d", &i);
		tmp=BST_previous(all, i);
		BST_insert(&all, i);
		if(tmp!=NULL && BST_search(right, tmp->val)==NULL){
			printf("%d ", tmp->val);
			BST_insert(&right, tmp->val);
		}
		else if((tmp=BST_next(all, i))!=NULL && BST_search(left, tmp->val)==NULL){
			printf("%d ", tmp->val);
			BST_insert(&left, tmp->val);
		}
	}
	printf("\n");
	return 0;
}

void BST_insert(BST **tarp, int val){
	/*
	  Inserts the number 'val' under the BST whose pointer is pointed by tarp
	 */
	BST *target = *tarp;
	if(target == NULL){
		//Make a new leaf node
		target = (BST *)malloc(sizeof(BST));
		target->val = val;
		target->h = 0;
		target->left = NULL;
		target->right = NULL;
		target->count = 1;
		target->w = 1;
		*tarp = target;  //Change the pointer value to the newly allocated node
		return ;
	}
	if(target->val ==val){
		//Number already present in the BST. Only need to increase the count.
		target->count++;
		target->w++;
	}
	else if(target->val > val){
		BST_insert(&(target->left), val);
	}
	else{
		BST_insert(&(target->right), val);
	}
	//Update values like height, weight etc.
	BST_update(tarp);
}

void BST_update(BST **tarp){
	/*
	  Updates 'w' and 'h' of the BST.
	  Make sure the children are updated before calling this for the parent.
	*/
	BST *target = *tarp;
	int lh, rh;
	if(target == NULL){
		return ;
	}
	target->w = BST_getw(target->left) + BST_getw(target->right) + target->count;
	lh = BST_geth(target->left);
	rh = BST_geth(target->right);
	if(lh > rh)
		target->h = lh+1;
	else
		target->h = rh+1;
	//Make sure the BST is balanced
	if(lh > rh+1 || rh > lh+1)
		BST_fixit(tarp);
}

int BST_getw(BST *target){
	if(target == NULL)
		return 0;
	return target->w;
}

int BST_geth(BST *target){
	//Set height of NULL to -1 to make height of leaf nodes as 0
	if(target == NULL)
		return -1;
	return target->h;
}

int BST_getc(BST *target){
	if(target == NULL)
		return 0;
	return target->count;
}

void BST_fixit(BST **tarp){
	/*
	  Fixes imbalanced BST
	 */
	BST *target = *tarp;
	if(BST_geth(target->left) > BST_geth(target->right)){
		if(BST_geth(target->left->left) > BST_geth(target->left->right)){
			BST_rotr(tarp);
			BST_update(&((*tarp)->right));
			BST_update(tarp);
		}
		else{
			BST_rotl(&(target->left));
			BST_rotr(tarp);
			target = *tarp;
			BST_update(&(target->left));
			BST_update(&(target->right));
			BST_update(tarp);
		}
	}
	else{
		if(BST_geth(target->right->right) > BST_geth(target->right->left)){
			BST_rotl(tarp);
			BST_update(&((*tarp)->left));
			BST_update(tarp);
		}
		else{
			BST_rotr(&(target->right));
			BST_rotl(tarp);
			target = *tarp;
			BST_update(&(target->right));
			BST_update(&(target->left));
			BST_update(tarp);
		}
	}
}

void BST_rotl(BST **tarp){
	/*
	  Rotates the node towards left ie. CCW
	 */
	BST *r, *target;
	target = *tarp;
	r = target->right;
	*tarp = r;
	target->right = r->left;
	r->left = target;
}

void BST_rotr(BST **tarp){
	/*
	  Rotates the node towards left ie. CCW
	 */
	BST *l, *target;
	target = *tarp;
	l = target->left;
	*tarp = l;
	target->left = l->right;
	l->right = target;
}

BST *BST_search(BST *target, int val){
	/*
	  Search for the node containing the number 'val'
	 */
	if(target == NULL)
		return NULL;
	if(target->val == val)
		return target;
	else if(target->val > val){
		return BST_search(target->left, val);
	}
	else{
		return BST_search(target->right, val);
	}
}

void BST_delete(BST **tarp, int val){
	/*
	  Delete the number 'val' from the BST
	 */
	BST *target;
	if(tarp == NULL)
		return ;
	target = *tarp;
	if(target->val == val){
		if(target->count > 0){
			target->count--;
			target->w--;
		}
	}
	else if(target->val > val){
		BST_insert(&(target->left), val);
	}
	else{
		BST_insert(&(target->right), val);
	}
	BST_update(tarp);
}

int BST_lessthan(BST *target, int val){
	/*
	  Return the number of elements in the BST lesser than 'val'
	 */
	if(target == NULL)
		return 0;
	if(target->val >= val){
		return BST_lessthan(target->left, val);
	}
	else{
		return BST_lessthan(target->right, val) + BST_getc(target) + BST_getw(target->left);
	}
}

int BST_greaterthan(BST *target, int val){
	/*
	  Return the number of elements in the BST greater than 'val'
	 */
	if(target == NULL)
		return 0;
	if(target->val <= val){
		return BST_greaterthan(target->right, val);
	}
	else{
		return BST_greaterthan(target->left, val) + BST_getc(target) + BST_getw(target->right);
	}
}

BST *BST_previous(BST *node, int val){
	if(node == NULL)
		return NULL;
	if(node->val < val){
		BST *tmp = BST_previous(node->right, val);
		if(tmp)
			return tmp;
		if(BST_getc(node)){
			return node;
		}
	}
	return BST_previous(node->left, val);
}

BST *BST_next(BST *node, int val){
	if(node == NULL)
		return NULL;
	if(node->val > val){
		BST *tmp = BST_next(node->left, val);
		if(tmp)
			return tmp;
		if(BST_getc(node)){
			return node;
		}
	}
	return BST_next(node->right, val);
}