Iahub recently has learned Bubble Sort, an algorithm that is used to sort a permutation with n elements a1, a2, ..., an in ascending order. He is bored of this so simple algorithm, so he invents his own graph. The graph (let's call it G) initially has n vertices and 0 edges. During Bubble Sort execution, edges appear as described in the following algorithm (pseudocode). 
    
    
      
    procedure bubbleSortGraph()  
        build a graph G with n vertices and 0 edges  
        repeat  
            swapped = false  
            for i = 1 to n - 1 inclusive do:  
                if a[i] > a[i + 1] then  
                    add an undirected edge in G between a[i] and a[i + 1]  
                    swap( a[i], a[i + 1] )  
                    swapped = true  
                end if  
            end for  
        until not swapped   
        /* repeat the algorithm as long as swapped value is true. */   
    end procedure  
    

For a graph, an independent set is a set of vertices in a graph, no two of which are adjacent (so there are no edges between vertices of an independent set). A maximum independent set is an independent set which has maximum cardinality. Given the permutation, find the size of the maximum independent set of graph G, if we use such permutation as the premutation a in procedure bubbleSortGraph.

Input

The first line of the input contains an integer n (2 ≤ n ≤ 105). The next line contains n distinct integers a1, a2, ..., an (1 ≤ ai ≤ n).

Output

Output a single integer — the answer to the problem. 

Examples

Input

3
3 1 2


Output

2

Note

Consider the first example. Bubble sort swaps elements 3 and 1. We add edge (1, 3). Permutation is now [1, 3, 2]. Then bubble sort swaps elements 3 and 2. We add edge (2, 3). Permutation is now sorted. We have a graph with 3 vertices and 2 edges (1, 3) and (2, 3). Its maximal independent set is [1, 2].
100
36 48 92 87 28 85 42 10 44 41 39 3 79 9 14 56 1 16 46 35 93 8 82 26 100 59 60 2 96 52 13 98 70 81 71 94 54 91 17 88 33 30 19 50 18 73 65 29 78 21 61 7 99 97 45 89 57 27 76 11 49 72 84 69 43 62 4 22 75 6 66 83 38 34 86 15 40 51 37 74 67 31 20 63 77 80 12 53 5 25 58 90 68 24 64 23 95 32 55 47
 5
4 2 1 3 5
 10
1 9 8 10 2 3 4 6 5 7
 50
12 24 42 43 36 3 40 29 7 34 10 13 28 9 35 23 25 21 19 4 20 18 11 38 41 48 6 46 33 17 31 37 2 30 32 44 45 5 47 49 16 15 50 27 26 14 39 22 1 8

16
 3
 6
 13

#include <bits/stdc++.h>
using namespace std;
template <typename T>
T min(T a, T b, T c) {
  return min(a, min(b, c));
}
template <typename T>
T max(T a, T b, T c) {
  return max(a, max(b, c));
}
template <typename T>
T max(T a, T b, T c, T d) {
  return max(a, max(b, max(c, d)));
}
template <typename T>
void read(vector<T> &arr, long long N) {
  arr.clear();
  arr.resize(N);
  for (long long i = 0; i < N; i++) cin >> arr[i];
}
template <typename T>
void read(vector<pair<T, T>> &arr, long long N) {
  arr.clear();
  arr.resize(N);
  for (long long i = 0; i < (long long)arr.size(); i++)
    cin >> arr[i].first >> arr[i].second;
}
template <typename T>
void read(vector<vector<T>> &arr, long long N, long long M) {
  arr.clear();
  arr.resize(N, vector<T>(M));
  for (long long i = 0; i < N; i++) {
    for (long long j = 0; j < M; j++) cin >> arr[i][j];
  }
}
template <typename T, size_t N>
long long SIZE(const T (&t)[N]) {
  return N;
}
template <typename T>
long long SIZE(const T &t) {
  return t.size();
}
string to_string(const string s, long long x1 = 0, long long x2 = 1e9) {
  return '"' + ((x1 < s.size()) ? s.substr(x1, x2 - x1 + 1) : "") + '"';
}
string to_string(const char *s) { return to_string((string)s); }
string to_string(const bool b) { return (b ? "true" : "false"); }
string to_string(const char c) { return string({c}); }
template <size_t N>
string to_string(const bitset<N> &b, long long x1 = 0, long long x2 = 1e9) {
  string t = "";
  for (long long __iii__ = min(x1, SIZE(b)), __jjj__ = min(x2, SIZE(b) - 1);
       __iii__ <= __jjj__; ++__iii__) {
    t += b[__iii__] + '0';
  }
  return '"' + t + '"';
}
template <typename A, typename... C>
string to_string(const A(&v), long long x1 = 0, long long x2 = 1e9,
                 C... coords);
long long l_v_l_v_l = 0, t_a_b_s = 0;
template <typename A, typename B>
string to_string(const pair<A, B> &p) {
  l_v_l_v_l++;
  string res = "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
  l_v_l_v_l--;
  return res;
}
template <typename A, typename... C>
string to_string(const A(&v), long long x1, long long x2, C... coords) {
  long long rnk = rank<A>::value;
  string tab(t_a_b_s, ' ');
  string res = "";
  bool first = true;
  if (l_v_l_v_l == 0) res += '\n';
  res += tab + "[";
  x1 = min(x1, SIZE(v)), x2 = min(x2, SIZE(v));
  auto l = begin(v);
  advance(l, x1);
  auto r = l;
  advance(r, (x2 - x1) + (x2 < SIZE(v)));
  for (auto e = l; e != r; e = next(e)) {
    if (!first) {
      res += ", ";
    }
    first = false;
    l_v_l_v_l++;
    if (e != l) {
      if (rnk > 1) {
        res += '\n';
        t_a_b_s = l_v_l_v_l;
      };
    } else {
      t_a_b_s = 0;
    }
    res += to_string(*e, coords...);
    l_v_l_v_l--;
  }
  res += "]";
  if (l_v_l_v_l == 0) res += '\n';
  return res;
}
void printm() { ; }
template <typename Heads, typename... Tails>
void printm(Heads H, Tails... T) {
  cout << to_string(H) << " | ";
  printm(T...);
}
bool lexi(string &s1, string &s2) {
  long long I = s1.size(), J = s2.size(), i = 0, j = 0;
  while (i < I and j < J) {
    if (s1[i] > s2[j]) return true;
    if (s1[i] < s2[j]) return false;
    i++;
    j++;
  }
  if (I >= J) return true;
  return false;
}
struct uf {
  vector<long long> par, size;
  void init(long long N) {
    par.resize(N, -1);
    size.resize(N, 1);
  }
  long long root(long long a) {
    if (par[a] == -1) return a;
    return par[a] = root(par[a]);
  }
  void unite(long long a, long long b) {
    a = root(a);
    b = root(b);
    if (a == b) return;
    if (size[a] < size[b]) {
      par[a] = b;
      size[b] += size[a];
    } else {
      par[b] = a;
      size[a] += size[b];
    }
  }
  bool same(long long a, long long b) {
    if (root(a) == root(b)) return true;
    return false;
  }
};
struct seg_tree {
  vector<long long> make;
  long long siz;
  vector<long long> arr;
  void init(vector<long long> &a, bool max, bool range) {
    arr.clear();
    make.clear();
    arr = a;
    siz = arr.size();
    make.resize(4 * siz);
    if (max)
      build_max(0, 0, siz - 1);
    else if (range)
      build_range(0, 0, siz - 1);
  }
  long long get_max(long long L, long long R) {
    return Get_max(0, 0, siz - 1, L, R);
  }
  void update_max(long long index, long long val) {
    Update_max(0, 0, siz - 1, index, val);
    return;
  }
  long long get_sum(long long L, long long R) {
    return Get_sum(0, 0, siz - 1, L, R);
  }
  void update_range(long long index, long long add) {
    Update_range(0, 0, siz - 1, index, add);
    return;
  }
  long long build_range(long long ind, long long L, long long R) {
    if (L == R) {
      make[ind] = arr[L];
      return make[ind];
    } else {
      long long mid = (L + R) / 2;
      long long a = build_range(2 * ind + 1, L, mid);
      long long b = build_range(2 * ind + 2, mid + 1, R);
      make[ind] = a + b;
      return make[ind];
    }
  }
  long long Get_sum(long long ind, long long L, long long R, long long Left,
                    long long Right) {
    if (L > Right or R < Left) return 0;
    if (Left <= L and R <= Right) return make[ind];
    long long mid = (L + R) / 2;
    long long a = Get_sum(2 * ind + 1, L, mid, Left, Right);
    long long b = Get_sum(2 * ind + 2, mid + 1, R, Left, Right);
    return a + b;
  }
  void Update_range(long long ind, long long L, long long R, long long index,
                    long long add) {
    if (L == R) {
      make[ind] = add;
      arr[index] = add;
    } else {
      long long mid = (L + R) / 2;
      if (L <= index and index <= R) {
        Update_range(2 * ind + 1, L, mid, index, add);
      } else {
        Update_range(2 * ind + 2, mid + 1, R, index, add);
      }
      make[ind] = make[2 * ind + 1] + make[2 * ind + 2];
    }
  }
  long long build_max(long long ind, long long L, long long R) {
    if (L == R) {
      make[ind] = arr[L];
      return make[ind];
    } else {
      long long mid = (L + R) / 2;
      return make[ind] = max(build_max(2 * ind + 1, L, mid),
                             build_max(2 * ind + 2, mid + 1, R));
    }
  }
  long long Get_max(long long ind, long long L, long long R, long long Left,
                    long long Right) {
    if (R < Left or L > Right) return -1e15;
    if (Left <= L and R <= Right) return make[ind];
    long long mid = (L + R) / 2;
    return max(Get_max(2 * ind + 1, L, mid, Left, Right),
               Get_max(2 * ind + 2, mid + 1, R, Left, Right));
  }
  long long Update_max(long long ind, long long L, long long R, long long index,
                       long long val) {
    if (L == R) {
      arr[index] = val;
      make[ind] = val;
      return val;
    } else {
      long long mid = (L + R) / 2;
      if (L <= index and index <= mid) {
        make[ind] = Update_max(2 * ind + 1, L, mid, index, val);
      } else {
        make[ind] = Update_max(2 * ind + 2, mid + 1, R, index, val);
      }
      make[ind] = max(make[2 * ind + 1], make[2 * ind + 2]);
      return make[ind];
    }
  }
};
static bool comp(pair<long long, long long> &a, pair<long long, long long> &b) {
  if (a.first < b.first) return true;
  if (a.first == b.first) {
    if (a.second < b.second) return true;
  }
  return false;
}
static bool comp1(vector<long long> &a, vector<long long> &b) {
  if (a[0] < b[0]) return true;
  if (a[0] == b[0] and a[1] > b[1]) return true;
  return false;
}
long long Max = 1e17, Min = -1e15;
long long N, M, K, D;
long long mod = 1e9;
long long P = 93;
void solve() {
  cin >> N;
  vector<long long> arr(N);
  for (long long i = 0; i < N; i++) {
    cin >> arr[i];
    --arr[i];
  }
  vector<long long> cnt(N);
  seg_tree var;
  var.init(cnt, true, false);
  for (long long i = 0; i < N; i++) {
    long long val = var.get_max(0, arr[i]) + 1;
    var.update_max(arr[i], val);
  }
  long long ans = 0;
  for (auto it : var.arr) {
    ans = max(ans, it);
  }
  cout << ans << '\n';
}
signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  auto start_time = chrono::high_resolution_clock::now();
  bool test = 0;
  if (!test)
    solve();
  else {
    long long tt;
    cin >> tt;
    while (tt--) solve();
  }
  auto end_time = chrono::high_resolution_clock::now();
  return 0;
}
