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.io.*;
import java.util.*;

public class Main {

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);
		int n=sc.nextInt();
		int []a=new int [n];
		TreeMap<Integer,Integer>map=new TreeMap();
		for(int i=0;i<n;i++) {
			a[i]=sc.nextInt()*-1;
			map.put(a[i],0);
		}
		int id=1;
		for(int x:map.keySet())
			map.put(x,id++);
		FenwickTree tree=new FenwickTree(n);
		int ans=0;
		for(int i=0;i<n;i++) {
			int curr=tree.query(map.get(a[i]))+1;
			ans=Math.max(ans, curr);
			tree.update(map.get(a[i]), curr);
		}
		out.println(ans);
		out.close();

	}
	static class FenwickTree{
		int []bit;
		FenwickTree(int n){
			bit=new int [n+1];
		}
		void update(int idx,int v) {
			while(idx<bit.length) {
				bit[idx]=Math.max(bit[idx], v);
				idx+=(idx&-idx);
			}
		}
		int query(int idx) {
			int ans=0;
			while(idx>0) {
				ans=Math.max(ans, bit[idx]);
				idx-=(idx&-idx);
			}
			return ans;
		}
	}
	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

		Scanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		Scanner(String fileName) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(fileName));
		}

		String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		String nextLine() throws IOException {
			return br.readLine();
		}

		int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		long nextLong() throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}

		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}

		boolean ready() throws IOException {
			return br.ready();
		}

	}

}