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: Time Limit Exceeded)

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

namespace abc134_e
{
    static class Program
    {
        static void Main(string[] args)
        {
            var n = Console.ReadLine().ToInteger();
            var a = new int[n];
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = Console.ReadLine().ToInteger();
            }

            //var n = 100000;
            //var a = new int[n];
            //for (int i = 0; i < a.Length; i++)
            //{
            //    a[i] = n - i;
            //}

            // 各色の最大値(最後の値)を小さい順に入れて置く<最大値, 最大値の個数>
            var colors = new List<Pair>();
            colors.Plus(0, a[0]);
            for (int i = 1; i < a.Length; i++)
            {
                // 各色の最後の値より大きいものの中で、最大の値を採用
                // どの色の最後の値よりも小さかったら、色を足す。
                var color = colors.Smaller(a[i]);
                colors.Minus(color);
                colors.Plus(color, a[i]);
            }

            Console.WriteLine($"{colors.Sum(m => m.Count)}");
        }

        static int ToInteger(this string s)
        {
            return int.Parse(s);
        }

        /// <summary>
        /// 二分検索で、指定した値よりも小さいもののうち、最後のインデックスを取得する
        /// </summary>
        /// <param name="list">検索する一覧</param>
        /// <param name="key">指定した値</param>
        /// <returns>指定した値よりも小さいもののうち、最後のインデックスを取得する</returns>
        static int Smaller(this List<Pair> list, int key)
        {
            // 開始位置
            var first = 0;
            // 終了位置+1
            var last = list.Count;
            while (first < last)
            {
                // 中央位置
                var middle = (last + first) / 2;
                // 中央位置を比較して、範囲を狭めていく
                if (list[middle].Number < key)
                {
                    first = middle + 1;
                }
                else
                {
                    last = middle;
                }
                if (list[middle].Number == key)
                {
                    first = middle;
                    last = middle;
                    break;
                }
            }

            if (first < 0)
            {
                first = 0;
            }

            if (first >= list.Count)
            {
                first = list.Count - 1;
            }
            
            if (list[first].Number >= key)
            {
                // セットした値が大きいので、ひとつ前にずらす
                first -= 1;
            }

            return first;
        }

        static int Larger(this List<Pair> list, int start, int key)
        {
            var ret = -1;

            if (start < 0)
            {
                start = 0;
            }

            var count = list.Count;
            for (int i = start; i < count; i++)
            {
                if (list[i].Number >= key)
                {
                    ret = i;
                    break;
                }
            }

            return ret;
        }

        static void Plus(this List<Pair> list, int later, int key)
        {
            var index = list.Larger(later, key);
            if (index >= 0)
            {
                var item = list[index];
                if (item.Number <= key)
                {
                    item.Count += 1;
                    list[index] = item;
                }
                else
                {
                    item = new Pair(key, 1);
                    list.Insert(index, item);
                }
            }
            else
            {
                var item = new Pair(key, 1);
                list.Add(item);
            }
        }

        static void Minus(this List<Pair> list, int index)
        {
            if (index >= 0)
            {
                var item = list[index];
                item.Count -= 1;
                if (item.Count > 0)
                {
                    list[index] = item;
                }
                else
                {
                    list.RemoveAt(index);
                }
            }
        }

    }

    struct Pair
    {
        public Pair(int number, int count)
        {
            Number = number;
            Count = count;
        }
        public int Number { get; set; }
        public int Count { get; set; }
    }

}