Problem:
Score : 500 points

Problem Statement

You are given a sequence with N integers: A = \{ A_1, A_2, \cdots, A_N \}.
For each of these N integers, we will choose a color and paint the integer with that color. Here the following condition must be satisfied:

If A_i and A_j (i < j) are painted with the same color, A_i < A_j.

Find the minimum number of colors required to satisfy the condition.

Constraints

1 \leq N \leq 10^5

0 \leq A_i \leq 10^9

Input

Input is given from Standard Input in the following format:

N
A_1
:
A_N

Output

Print the minimum number of colors required to satisfy the condition.

Sample Input 1

5
2
1
4
5
3

Sample Output 1

2

We can satisfy the condition with two colors by, for example, painting 2 and 3 red and painting 1, 4, and 5 blue.

Sample Input 2

4
0
0
0
0

Sample Output 2

4

We have to paint all the integers with distinct colors.

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

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


namespace AtCoder
{
    partial class Program
    {
		static int ReadInt()
        {
            return int.Parse(Console.ReadLine());
        }
        static long ReadLong()
        {
            return long.Parse(Console.ReadLine());
        }
        static int[] ReadIntArray()
        {
            return Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
        }
        static int[] ReadIntArray(int n)
        {
            var a = new int[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = ReadInt();
            }
            return a;
        }
        static long[] ReadLongArray()
        {
            return Console.ReadLine().Split(' ').Select(long.Parse).ToArray();
        }
        static long[] ReadLongArray(int n)
        {
            var a = new long[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = ReadLong();
            }
            return a;
        }
		
        public static int[] ZAlgotithm(string s)
        {
            var len = s.Length;

            var a = new int[len];
            a[0] = len;
            var i = 1;
            var j = 0;
            while (i < len)
            {
                while (i + j < len && s[j] == s[i + j]) j++;
                a[i] = j;

                if (j == 0)
                {
                    i++;
                    continue;
                }

                var k = 1;
                while (i + k < len && k + a[k] < j)
                {
                    a[i + k] = a[k];
                    k++;
                }
                i += k;
                j -= k;
            }

            return a;
        }
        public class MaxHeap<T> : IEnumerable<T>
        {
            private List<T> _list;
            private Comparer<T> _comp;
			
            public int Count
            {
                get
                {
                    return _list.Count;
                }
            }
            public MaxHeap() : this(0) { }
            public MaxHeap(int capacity, Comparison<T> comp=null)
            {
                _list = new List<T>(capacity);

                if (comp == null)
                {
                    _comp = Comparer<T>.Default;
                }
                else
                {
                    _comp = Comparer<T>.Create(comp);
                }
            }
            
            public void Push(T elem)
            {
                Upheap(elem);
            }

            public T Pop()
            {
                return Downheap();
            }

            public T Peek()
            {
                return _list[0];
            }

            
            private void Swap(int i, int j)
            {
                var a = _list[j];
                _list[j] = _list[i];
                _list[i] = a;
            }

            private void Upheap(T elem)
            {
                _list.Add(elem);
                var i = _list.Count - 1;

                while (true)
                {
                    if (i == 0) return;
                    var j = (i - 1) / 2;

                    var e = _list[i];
                    var p = _list[j];

                    var c = _comp.Compare(e, p);
                    if (c > 0)
                    {
                        Swap(i, j);
                        i = j;
                        continue;
                    }
                    else
                    {
                        break;
                    }
                }
            }

            private T Downheap()
            {
                var result = _list[0];

                var last = _list.Count - 1;
                Swap(0, last);
                _list.RemoveAt(last);
                if (_list.Count == 0) return result;

                var i = 0;
                while (true)
                {
                    if (i == _list.Count - 1) return result;
                    var p = _list[i];

                    var j = i * 2 + 1;
                    if (j >= _list.Count) return result;

                    if(j+1 < _list.Count && _comp.Compare(_list[j], _list[j+1]) < 0)
                    {
                        j++;
                    }

                    if (_comp.Compare(_list[i], _list[j]) < 0)
                    {
                        Swap(i, j);
                        i = j;
                    }
                    else
                    {
                        return result;
                    }
                }
            }
            public MaxHeap<T> Copy(Comparison<T> comp=null)
            {
                var c = new MaxHeap<T>(0, comp);
                c._list = _list.ToList();

                return c;
            }
            public MaxHeap(List<T> list)
            {
                _list = list;

                _comp = Comparer<T>.Default;
            }

            public List<T> GetList()
            {
                return _list;
            }

            public IEnumerator<T> GetEnumerator()
            {
                return _list.GetEnumerator();
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }
        class InputLine
        {
            private string[] _inputs;
            private int _index = 0;

            InputLine(string input)
            {
                _inputs = input.Split();
                _index = 0;
            }

            public static InputLine Read()
            {
                return new InputLine(Console.ReadLine());
            }

            public int NextInt()
            {
                return int.Parse(_inputs[_index++]);
            }
            public long NextLong()
            {
                return long.Parse(_inputs[_index++]);
            }
            public double NextDouble()
            {
                return double.Parse(_inputs[_index++]);
            }
        }
        public static int GCD(int x, int y)
        {
            var a = Math.Max(x, y);
            var b = x + y - a;

            while (b != 0)
            {
                var c = b;
                b = a % b;
                a = c;
            }

            return a;
        }
        public static long GCD(long x, long y)
        {
            var a = Math.Max(x, y);
            var b = x + y - a;

            while (b != 0)
            {
                var c = b;
                b = a % b;
                a = c;
            }

            return a;
        }
        static long ModPower(long x, long y, long mod)
        {
            var bytes = BitConverter.GetBytes(y);
            var bits = new System.Collections.BitArray(bytes);

            var max2 = 0;
            for (int i = bits.Length - 1; i >= 0; i--)
            {
                if (bits[i])
                {
                    max2 = i;
                    break;
                }
            }

            long result = 1;
            for (int i = max2; i >= 0; i--)
            {
                result = (result * result) % mod;
                if (bits[i])
                {
                    result = (result * x) % mod;
                }
            }

            return result;
        }
        
        static long ModFact(long n, long mod)
        {
            long result = 1;

            for (int i = 1; i <= n; i++)
            {
                result = result * i % mod;
            }
            return result;
        }

        static long ModMal(long x, long y, long mod)
        {
            return ((x % mod) * (y % mod)) % mod;
        }

        static long ModDiv(long x, long y, long mod)
        {
            //フェルマーの小定理より、a^(-1) = a^(p-2)
            return ModMal(x, ModPower(y, mod - 2, mod), mod);
        }
        static long ModComb(long n, long r, long mod)
        {
            long numerator = 1;
            for (int i = 0; i < r; i++)
            {
                numerator = ModMal(numerator, n - i, mod);
            }

            long denominator = ModFact(r, mod);

            return ModDiv(numerator, denominator, mod);
        }
        class Graph
        {
            private int _size;
            private List<int>[] _map;

            public IEnumerable<int> this[int i]
            {
                get
                {
                    if (_map[i] == null) return Enumerable.Empty<int>();
                    return _map[i];
                }
            }

            public Graph(int size)
            {
                _size = size;
                _map = new List<int>[size];
            }

            public void Add(int from, int to)
            {
                if (_map[from] == null)
                {
                    _map[from] = new List<int>();
                }
                _map[from].Add(to);
            }
        }
        static long p1097 = 1000000007;
        static void Main(string[] args)
        {
			//↓

            var n = ReadInt();
            var aas = ReadIntArray(n);
            var l = new List<int>();
            for (int i = n - 1; i >= 0; i--)
            {
                var a = aas[i];

                var k = l.UpperBound(a);
                if (k > l.Count - 1) l.Add(a);
                else l[k] = a;
            }

            Console.WriteLine(l.Count);


			//↑
        }

	}
    static class Extensions
    {
        public static int LowerBound<T>(this IList<T> list, T value, IComparer<T> comp=null)
        {
            if (comp == null) comp = Comparer<T>.Default;

            var l = 0;
            var r = list.Count;

            while (l < r)
            {
                var m = (l + r) / 2;
                var c = comp.Compare(value, list[m]);
                if (c > 0) l = m + 1;
                else  r = m;
            }

            return l;
        }
        public static int UpperBound<T>(this IList<T> list, T value, IComparer<T> comp=null)
        {
            if (comp == null) comp = Comparer<T>.Default;

            var l = 0;
            var r = list.Count;

            while (l < r)
            {
                var m = (l + r) / 2;
                var c = comp.Compare(value, list[m]);
                if (c >= 0) l = m + 1;
                else r = m;
            }

            return r;
        }
    }
}