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 Java8 (OpenJDK 1.8.0) (judge verdict: Accepted)

import java.util.ArrayList;
import java.util.Scanner;
class Main{


	static char[][] map;

	static long[][] c;
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);			//文字の入力
		int n = sc.nextInt();
		int[] a = new int[n];
		for(int i = 0;i < n;i++){
			a[i] = sc.nextInt();
		}

		ArrayList<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
		int ans = 0;
		
		for(int i = 0;i < n;i++){
			if(list.size() == 0){
				ArrayList<Integer> sub = new ArrayList<Integer>();
				sub.add(a[i]);
				list.add(sub);
			}else{
				int vail = -1;
				int candidate = -1;
				int candidatenum = -1;
				
				int left = 0;
				int right = list.size()-1;
//				System.out.println(i + " i ");
				
				int count = 0;
				while(right - left > 0){
//					System.out.println(right + " right ");
					
					int mid = (left + right)/2;
					if(list.get(mid).get(0) >= a[i]){
						left = mid+1;
					}else{
						right = mid;
					}
					count++;
//					if(count >= 4){
//						System.out.println("aa");
//						return;
//					}
				}
//				
//				
//				for(int j = 0;j < list.size();j++){
//					if(list.get(j).get(0) < a[i] &&  candidatenum <list.get(j).get(0) ){ 			//a[i] < a[j} でかつその中から最大の値をpeakをもつstackを見つける
// 						candidate = j;
//						candidatenum = list.get(j).get(0);
//						vail = 0;
//					}
//				}
				
				if( list.get(left).get(0) < a[i]){					//候補がいればそこにa[i]を追加
					list.get(left).set(0,a[i]);
				}else{							//候補がなければ新しくstackを追加
					ArrayList<Integer> sub = new ArrayList<Integer>();
					sub.add(a[i]);
					list.add(sub);
				}
			}
			
		}
			
		System.out.println(list.size());

	}



	static int gcd(int a,int b){				//最大公約数を返す
		if(b == 0){
			return a;
		}else{
			return gcd(b, a%b);
		}
	}
	static long gcd(long a,long b){
		if(b == 0){
			return a;
		}else{
			return gcd(b, a%b);
		}
	}



	static long lcm (long a, long b) {
		long g = gcd(a,b);
		return a/g*b;
	}




}



class Pair implements Comparable{
	int from;
	int end;
	@Override
	public int compareTo(Object other) {
		Pair otherpair = (Pair)other;

		return   end- otherpair.end;
	}








}