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.IO;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        var N = sc.ReadInt();
        var A = sc.ReadIntArray(N);
        var t = new Treap<int>();
        for (int i = 0; i < N; i++)
        {
            if (t.Length == 0)
            {
                t.Insert(A[i]);
                continue;
            }
            var x = t.LowerBouond(A[i]);
            if (x == 0)
            {
                t.Insert(A[i]);
            }
            else
            {
                var val = t[x - 1];
                t.Erase(val);
                t.Insert(A[i]);
            }
        }
        var ans = t.Length;
        Console.WriteLine(ans);
    }
    class Treap<T>
    {
        public int Length
        {
            get { return this.Root == null ? 0 : this.NodeCount(this.Root); }
        }
        public T this[int i]
        {
            get
            {
                if (this.Root.Count < i - 1) throw new IndexOutOfRangeException();
                return this.Root.Get(i);
            }
        }
        public Node Root;
        private IComparer<T> Cmp = Comparer<T>.Default;
        public Treap(IComparer<T> cmp = null)
        {
            if (cmp != null) this.Cmp = cmp;
        }
        public Node Merge(Node l, Node r)
        {
            if (l == null || r == null) return l == null ? r : l;

            if (l.Priority > r.Priority)
            {
                l.R = this.Merge(l.R, r);
                return this.Update(l);
            }
            else
            {
                r.L = this.Merge(l, r.L);
                return this.Update(r);
            }
        }
        public Tuple<Node, Node> Split(int k) { return this.Split(this.Root, k); }
        public Tuple<Node, Node> Split(Node t, int k)
        {
            if (t == null) return Tuple.Create<Node, Node>(null, null);
            if (k <= this.NodeCount(t.L))
            {
                var s = this.Split(t.L, k);
                t.L = s.Item2;
                return Tuple.Create(s.Item1, this.Update(t));
            }
            else
            {
                var s = this.Split(t.R, k - this.NodeCount(t.L) - 1);
                t.R = s.Item1;
                return Tuple.Create(this.Update(t), s.Item2);
            }
        }
        public Node Update(Node node)
        {
            node.Count = this.NodeCount(node.L) + this.NodeCount(node.R) + 1;
            return node;
        }
        public int NodeCount(Node node)
        {
            return node == null ? 0 : node.Count;
        }
        public int LowerBouond(T value) { return this.LowerBouond(this.Root, value); }
        public int LowerBouond(Node node, T value)
        {
            if (node == null) return 0;
            if (this.Cmp.Compare(value, node.Value) <= 0)
                return this.LowerBouond(node.L, value);
            else
                return this.NodeCount(node.L) + 1 + this.LowerBouond(node.R, value);
        }
        public int UpperBound(T value) { return this.UpperBound(this.Root, value); }
        public int UpperBound(Node node, T value)
        {
            if (node == null) return 0;
            if (this.Cmp.Compare(value, node.Value) >= 0)
                return this.NodeCount(node.L) + 1 + this.UpperBound(node.R, value);
            else
                return this.UpperBound(node.L, value);
        }
        public int ValueCount(T value)
        {
            return this.UpperBound(value) - this.LowerBouond(value);
        }
        public void Insert(T value)
        {
            var sub = this.Split(this.Root, this.LowerBouond(value));
            var newNode = new Node(value);
            var merged = this.Merge(sub.Item1, newNode);
            this.Root = this.Merge(merged, sub.Item2);
        }
        public void Erase(T value)
        {
            if (this.ValueCount(value) == 0) return;
            var sub = this.Split(this.Root, this.LowerBouond(value));
            this.Root = this.Merge(sub.Item1, this.Split(sub.Item2, 1).Item2);
        }
        public class Node
        {
            private static Random Rand = new Random();
            public T Value { get; set; }
            public Node L { get; set; } = null;
            public Node R { get; set; } = null;
            public int Count { get; set; }
            public double Priority { get; set; }
            public Node(T value, double priority)
            {
                this.Value = value;
                this.Priority = priority;
                this.Count = 1;
            }
            public Node(T value) : this(value, Rand.NextDouble()) { }
            public T Get(int i)
            {
                var lcount = 0;
                if (this.L != null) lcount = this.L.Count;
                if (lcount == i) return this.Value;
                else if (lcount < i) return this.R.Get(i - lcount - 1);
                else return this.L.Get(i);
            }
        }
    }
    static Scanner sc = new Scanner();
}
class Scanner
{
    string[] S = new string[0];
    int Index = 0;
    char[] Separators = new char[] { ' ' };

    public string Next()
    {
        if (this.Index < this.S.Length) return this.S[this.Index++];
        var line = "";
        while (line == "") line = Console.ReadLine();
        this.S = line.Split(this.Separators, StringSplitOptions.RemoveEmptyEntries);
        if (this.S.Length == 0) return this.Next();
        this.Index = 0;
        return this.S[this.Index++];
    }
    public string ReadStr()
    {
        return this.Next();
    }
    public char ReadChar()
    {
        return this.Next()[0];
    }
    public int ReadInt()
    {
        return int.Parse(this.Next());
    }
    public uint ReadUInt()
    {
        return uint.Parse(this.Next());
    }
    public long ReadLong()
    {
        return long.Parse(this.Next());
    }
    public double ReadDouble()
    {
        return double.Parse(this.Next());
    }
    public Tuple<int, int> ReadTup(int add = 0)
    {
        return Tuple.Create(this.ReadInt() + add, this.ReadInt() + add);
    }
    public Tuple<long, long> ReadTupLong(int add = 0)
    {
        return Tuple.Create(this.ReadLong() + add, this.ReadLong() + add);
    }
    public Tuple<int, int, int> ReadTup3(int add = 0)
    {
        return Tuple.Create(this.ReadInt() + add, this.ReadInt() + add, this.ReadInt() + add);
    }
    public Tuple<int, int, int, int> ReadTup4(int add = 0)
    {
        return Tuple.Create(this.ReadInt() + add, this.ReadInt() + add, this.ReadInt() + add, this.ReadInt() + add);
    }
    public int[] ReadIntArray(int n)
    {
        var array = new int[n];
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = this.ReadInt();
        }
        return array;
    }
    public long[] ReadLongArray(int n)
    {
        var array = new long[n];
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = this.ReadLong();
        }
        return array;
    }
    public double[] ReadDoubleArray(int n)
    {
        var array = new double[n];
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = this.ReadDouble();
        }
        return array;
    }
    public char[] ReadCharArray(int n)
    {
        var array = new char[n];
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = this.ReadChar();
        }
        return array;
    }
    public string[] ReadStrArray(int n)
    {
        var array = new string[n];
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = this.ReadStr();
        }
        return array;
    }
    public Tuple<long, long>[] ReadTupLongArray(int n, int add = 0)
    {
        var array = new Tuple<long, long>[n];
        for (int i = 0; i < n; i++)
        {
            array[i] = this.ReadTupLong(add);
        }
        return array;
    }
    public Tuple<int, int>[] ReadTupArray(int n, int add = 0)
    {
        var array = new Tuple<int, int>[n];
        for (int i = 0; i < n; i++)
        {
            array[i] = this.ReadTup(add);
        }
        return array;
    }
    public Tuple<int, int, int>[] ReadTup3Array(int n, int add = 0)
    {
        var array = new Tuple<int, int, int>[n];
        for (int i = 0; i < n; i++)
        {
            array[i] = this.ReadTup3(add);
        }
        return array;
    }
    public Tuple<int, int, int, int>[] ReadTup4Array(int n, int add = 0)
    {
        var array = new Tuple<int, int, int, int>[n];
        for (int i = 0; i < n; i++)
        {
            array[i] = this.ReadTup4(add);
        }
        return array;
    }
}