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.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Collections;

static class Extensions
{
    public static int ToInt(this string s) => int.Parse(s);
    public static long ToLong(this string s) => long.Parse(s);
    public static char ToChar(this string s) => char.Parse(s);
    public static double ToDouble(this string s) => double.Parse(s);
    public static int[] ToIntArray(this string s) => s.Replace(',', ' ').Split(' ').Select(x => x.ToInt()).ToArray();
    public static long[] ToLongArray(this string s) => s.Replace(',', ' ').Split(' ').Select(x => x.ToLong()).ToArray();
    public static double[] ToDoubleArray(this string s) => s.Replace(',', ' ').Split(' ').Select(x => x.ToDouble()).ToArray();
    public static Queue<T> ToQueue<T>(this IEnumerable<T> seq) => new Queue<T>(seq);
    public static Stack<T> ToStack<T>(this IEnumerable<T> seq) => new Stack<T>(seq);
    public static HashSet<T> ToHashSet<T>(this IEnumerable<T> seq) => new HashSet<T>(seq);
}
static class MyMath
{
    static public long GCD(long a, long b) => (a < b) ? GCD(b, a) : ((b == 0) ? a : GCD(b, a % b));
    static public long LCM(long a, long b) => (a > b) ? (a / GCD(a, b) * b) : (b / GCD(a, b) * a);
    static private readonly long _m = 1000000000 + 7;
    static public long Mod(long val) => (val % _m + _m) % _m;
    static private long extGCD(long a, long b, ref long x, ref long y) => (b == 0) ? (a + (x = 1) * 0 + (y = 0) * 0) : (extGCD(b, a % b, ref y, ref x) + (y -= a / b * x) * 0);
    static public long ModInverse(long a, long dummy1 = 0, long dummy2 = 0) => extGCD(a, _m, ref dummy1, ref dummy2) * 0 + Mod(dummy1);    
}

class Program
{
    static string[] ReadLines(int n) => Enumerable.Range(0, n).Select(s => Console.ReadLine()).ToArray();

    static void Main()
    {
        int N = Console.ReadLine().ToInt();
        long[] array = ReadLines(N).Select(s => s.ToLong()).ToArray();

        //降順
        List<long> xxx = new List<long>();

        foreach (var n in array)
        {
            var x = helper(xxx, n);

            if (x < 0)
            {
                xxx.Add(n);                
            }
            else
            {
                xxx[x] = n;
            }
        }

        Console.WriteLine(xxx.Count);
    }

    static int helper (IList<long> list, long val)
    {
        if (list.Count == 0) return -1;
        
        int left = 0;
        int right = list.Count - 1;
        
        if (list[0] < val) return 0;
        
        if (list[list.Count - 1] >= val) return -1;

        while (right - left > 1)
        {
            int mid = (right - left) / 2 + left; 
            if (list[mid] < val)
            {
                right = mid;
            }
            else
            {
                left = mid;
            }
        }
        
        return right;
    }
    
}