using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Console;

class Program
{
    static void Main(string[] args)
    {
        new Program().Calc();
    }

    Scanner cin;

    public Program() { }

    bool chmax<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) < 0) { a = b; return true; } return false; }
    bool chmin<T>(ref T a, T b) where T : IComparable<T> { if (b.CompareTo(a) < 0) { a = b; return true; } return false; }

    void Calc()
    {
        cin = new Scanner();

        Treap<int> treap = new Treap<int>();


        int N = cin.nextInt();



        int ans = 0;
        int prev = cin.nextInt();

        treap.Insert(prev);


        for (int i = 1; i < N; ++i)
        {
            int A = cin.nextInt();

            int index = treap.FindIndex(A);

            if (index == treap.Count())
            {
                treap.Erase(treap[treap.Count() - 1]);
                treap.Insert(A);
            }
            else if (index == 0 || A == 0)
            {
                treap.Insert(A);
            }
            else
            {
                if (A == treap[index])
                {
                    int indexPrev = treap.FindIndex(A - 1);
                    if (A - 1 == treap[indexPrev])
                    {
                        treap.Erase(treap[indexPrev]);
                        treap.Insert(A);
                    }
                    else
                    {
                        if (indexPrev == 0)
                        {
                            treap.Insert(A);
                        }
                        else
                        {
                            treap.Erase(treap[indexPrev - 1]);
                            treap.Insert(A);
                        }
                    }
                }
                else
                {
                    treap.Erase(treap[index - 1]);
                    treap.Insert(A);
                }
            }
        }

        WriteLine(treap.Count());
    }
}

class Treap<T> where T : IComparable
{
    private class Node
    {
        private static Random g_rand = new Random();
        private readonly int m_rank = g_rand.Next();
        private readonly T m_value;
        private Node m_lch;
        private Node m_rch;
        private int m_count;

        public Node(T value)
        {
            m_value = value;
            m_count = 1;
        }

        public static int Count(Node node)
        {
            return (node != null) ? node.m_count : 0;
        }

        private Node Update()
        {
            m_count = Count(m_lch) + Count(m_rch) + 1;
            return this;
        }

        public static Node Merge(Node a, Node b)
        {
            if (a == null) { return b; }
            if (b == null) { return a; }
            if (a.m_rank < b.m_rank)
            {
                a.m_rch = Merge(a.m_rch, b);
                return a.Update();
            }
            else
            {
                b.m_lch = Merge(a, b.m_lch);
                return b.Update();
            }
        }

        public static Tuple<Node, Node> Split(Node t, int k)
        {
            if (t == null) { return new Tuple<Node, Node>(null, null); }
            if (k <= Count(t.m_lch))
            {
                var pair = Split(t.m_lch, k);
                t.m_lch = pair.Item2;
                return new Tuple<Node, Node>(pair.Item1, t.Update());
            }
            else
            {
                var pair = Split(t.m_rch, k - Count(t.m_lch) - 1);
                t.m_rch = pair.Item1;
                return new Tuple<Node, Node>(t.Update(), pair.Item2);
            }
        }

        public int FindIndex(T value)
        {
            int L = Count(m_lch);
            if (value.CompareTo(m_value) < 0)
            {
                return (m_lch != null) ? m_lch.FindIndex(value) : 0;
            }
            else if (value.CompareTo(m_value) > 0)
            {
                return (m_rch != null) ? m_rch.FindIndex(value) + L + 1 : L + 1;
            }
            else
            {
                return L;
            }
        }

        public T this[int i]
        {
            get
            {
                int L = Count(m_lch);
                if (i < L)
                {
                    return m_lch[i];
                }
                else if (i > L)
                {
                    return m_rch[i - L - 1];
                }
                else
                {
                    return m_value;
                }
            }
        }
    }

    private Node node;

    public void Insert(T value)
    {
        if (node != null)
        {
            int k = node.FindIndex(value);
            var pair = Node.Split(node, k);
            node = Node.Merge(Node.Merge(pair.Item1, new Node(value)), pair.Item2);
        }
        else
        {
            node = new Node(value);
        }
    }

    public void Erase(T value)
    {
        if (node != null)
        {
            int k = node.FindIndex(value);
            var pair = Node.Split(node, k);
            var pair2 = Node.Split(pair.Item2, 1);
            node = Node.Merge(pair.Item1, pair2.Item2);
        }
    }

    public int Count()
    {
        return Node.Count(node);
    }

    /// <summary>
    /// 値がvalueなインデックスを返す
    /// valueが無いときは、value以上の値で一番小さいやつのインデックスを返す
    /// valueが全ての値よりも大きい場合は、インデックスはノードの個数を返す。
    /// （存在するインデックスよりもひとつ大きな値（＝ノードの個数の値）を返す）
    /// ※↑のインデックスで、treap[index]として参照しようとすると配列の範囲外アクセスで例外で止まってしまうので注意。
    /// ※もし、値がvalueなノードが複数ある場合、どのノードのindexが返るか不定なので注意。
    /// ※※もし、ノードがひとつも無い場合（Treapクラスのメンバ変数nodeがnullな場合）はnullアクセスで例外となるので注意。
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public int FindIndex(T value)
    {
        return node.FindIndex(value);
    }

    public T this[int i]
    {
        get
        {
            return node[i];
        }
    }
}

public static class StringExtension
{
    public static char GetChar1(this string str, int indexOneBase)
    {
        return str[indexOneBase - 1];
    }
}

class Scanner
{
    string[] s;
    int i;

    char[] cs = new char[] { ' ' };

    public Scanner()
    {
        s = new string[0];
        i = 0;
    }

    public string next()
    {
        if (i < s.Length) return s[i++];
        string st = Console.ReadLine();
        while (st == "") st = Console.ReadLine();
        s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
        if (s.Length == 0) return next();
        i = 0;
        return s[i++];
    }

    public int nextInt()
    {
        return int.Parse(next());
    }
    public int[] ArrayInt(int N, int add = 0)
    {
        int[] Array = new int[N];
        for (int i = 0; i < N; i++)
        {
            Array[i] = nextInt() + add;
        }
        return Array;
    }

    public long nextLong()
    {
        return long.Parse(next());
    }

    public long[] ArrayLong(int N, long add = 0)
    {
        long[] Array = new long[N];
        for (int i = 0; i < N; i++)
        {
            Array[i] = nextLong() + add;
        }
        return Array;
    }

    public double nextDouble()
    {
        return double.Parse(next());
    }


    public double[] ArrayDouble(int N, double add = 0)
    {
        double[] Array = new double[N];
        for (int i = 0; i < N; i++)
        {
            Array[i] = nextDouble() + add;
        }
        return Array;
    }
}


Measured memory_bytes: 20920