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: Wrong Answer)

using System;
using System.Collections.Generic;//list用
using System.Collections;
using System.Linq;
class Program
{
    static List<int> s = new List<int>();
    static List<int> t = new List<int>();
    static decimal result;
static int N;
    static void Main()
    {
Read1();
Read2();
      Treap<int> tr=new Treap<int>();
for(int i=0;i<N;i++)
{
  int saveMax=-1;
  int savej=0;
  //s[i]が最大になるグループで，かつ今の最大値が一番大きいグループに配属させたい。に

  //総当たりだと10^5ループの中に10^5ループが入るので間に合わない。
/*
  for(int j=0;j<result;j++)
  {
      if(t[j]<s[i] && t[j]>saveMax){saveMax=t[j];savej=j;}
  }
          //更新可能な奴がいなければtに新規追加。あればそいつを更新。
  if(saveMax==-1){t.Add(s[i]);result++;}else{t[savej]=s[i];}  
  */
  //二分木で計算削減
  //i==0の時は追加
  if(i==0){tr.Insert(s[i]);result++;}else{
//現存要素の最小より小さいなら新規追加
    if(tr.FindIndex(s[i])==0){tr.Insert(s[i]);result++;}else{
      //違うなら，現存要素の中で自分より小さいものの中の最大と差し替え
      tr.Change(s[i]);}
  }
  

  
}     
Console.WriteLine(result.ToString());

    }

    static void Read1()
    {
        string tmp = Console.ReadLine();
        N = int.Parse(tmp);
    }

    static void Read2()
    {
        string tmp;
      for(int i=0;i<N;i++)
      {
      tmp=Console.ReadLine();
        s.Add(int.Parse(tmp));
      }
    }
}

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;
        }

        private 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 int FindIndex(T value)
    {
        return node.FindIndex(value);
    }

    public T this[int i]
    {
        get
        {
            return node[i];
        }
    }
    
    //一個前の要素を差し替える
    public void Change(T value)
    {
            int k = node.FindIndex(value);
            var pair = Node.Split(node, k-1);
            var pair2= Node.Split(node, k);
            node = Node.Merge(Node.Merge(pair.Item1, new Node(value)), pair2.Item2);
    }
}