import java.util.Scanner; //rename class to Main to submit on codechef public class CHRL3 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int N = scanner.nextInt(); int[] A = new int[N]; for (int i = 0; i < N; i++) { A[i] = scanner.nextInt(); } int max; //max = subtask2(N, A); max = subtask3(N, A); System.out.println(max); } private static int subtask3(int n, int[] a) { int max = 0; int[] dp = new int[n]; int maxInArray = 0; for (int i : a) { if (i > maxInArray) maxInArray = i; } SegmentTree segmentTree = new SegmentTree(maxInArray + 1); for (int i = 0; i < n; i++) { int maxLeft = segmentTree.getMaxRight(a[i]); dp[i] = maxLeft + 1; if (dp[i] > max) max = dp[i]; segmentTree.update(a[i], dp[i]); } return max; } private static int subtask2(int n, int[] a) { int max = 0; int[] dp = new int[n]; for (int i = 0; i < n; i++) { int maxLeft = 0; for (int j = 0; j < i; j++) { if (a[j] > a[i] && dp[j] > maxLeft) maxLeft = dp[j]; } dp[i] = maxLeft + 1; if (dp[i] > max) max = dp[i]; } return max; } public static class SegmentTree { int size; int twiceSize; int[] A; public SegmentTree(int noOfElements) { this.size = nearestPowerOfTwo(noOfElements); twiceSize = size << 1; A = new int[twiceSize]; } private int nearestPowerOfTwo(int x) { int ans = 1; while (ans < x) { ans = ans << 1; } return ans; } public int getMaxRight(int idx) { int max = 0; idx += size; int prevIdx = idx; idx = idx >> 1; while (idx != 0) { if (prevIdx % 2 == 0) max = Math.max(max, A[idx]); prevIdx = idx; idx = idx >> 1; } return max; } public void update(int idx, int val) { idx += size; int prevIdx = idx; idx = idx >> 1; while (idx != 0) { if (prevIdx % 2 == 1) A[idx] = Math.max(A[idx], val); prevIdx = idx; idx = idx >> 1; } } } }