#include <bits/stdc++.h>
using namespace std;
const long long linf = 1e18;
const double eps = 1e-12;
const double pi = acos(-1);
template <typename T>
istream& operator>>(istream& is, vector<T>& vec) {
  for (auto&& x : vec) is >> x;
  return is;
}
template <typename T>
ostream& operator<<(ostream& os, const vector<T>& vec) {
  for (long long i = (0), __last_i = (vec.size()); i < __last_i; i++) {
    if (i) os << " ";
    os << vec[i];
  }
  return os;
}
template <typename T>
ostream& operator<<(ostream& os, const vector<vector<T>>& vec) {
  for (long long i = (0), __last_i = (vec.size()); i < __last_i; i++) {
    if (i) os << endl;
    os << vec[i];
  }
  return os;
}
template <class Monoid>
class SegmentTree {
  using T = typename Monoid::type;
  const int size_, n;
  std::vector<T> data;
  int expand(int m) const { return m == 1 ? m : expand((m + 1) / 2) * 2; }

 public:
  SegmentTree(const std::vector<T>& vec)
      : size_(vec.size()), n(expand(size_)), data(n * 2, Monoid::id()) {
    std::copy(begin(vec), end(vec), begin(data) + n);
    for (long long i = (n)-1, __last_i = (0); i >= __last_i; i--) {
      data[i] = Monoid::op(data[i * 2 + 0], data[i * 2 + 1]);
    }
  }
  SegmentTree(const int count, const T& value = Monoid::id())
      : SegmentTree(std::vector<T>(count, value)) {}
  int size() const { return size_; }
  void update(int pos, const T& value) {
    assert(0 <= pos && pos < size_);
    data[pos += n] = value;
    while (pos /= 2) {
      data[pos] = Monoid::op(data[pos * 2], data[pos * 2 + 1]);
    }
  }
  T find(int l, int r) const {
    assert(0 <= l && l <= r && r <= size_);
    l += n;
    r += n;
    T res1 = Monoid::id(), res2 = Monoid::id();
    while (l != r) {
      if (l % 2) res1 = Monoid::op(res1, data[l++]);
      if (r % 2) res2 = Monoid::op(data[--r], res2);
      l /= 2;
      r /= 2;
    }
    return Monoid::op(res1, res2);
  }
  using value_type = T;
  using update_type = T;
};
struct Min {
  using type = long long;
  static type id() { return linf; }
  static type op(const type& l, const type& r) { return min(l, r); }
};
struct Max {
  using type = long long;
  static type id() { return -linf; }
  static type op(const type& l, const type& r) { return max(l, r); }
};
struct Sum {
  using type = long long;
  static type id() { return 0; }
  static type op(const type& l, const type& r) { return l + r; }
};
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  const long long M = 20;
  long long n;
  cin >> n;
  vector<long long> a(n);
  cin >> a;
  SegmentTree<Min> seg(n);
  map<long long, vector<long long>> ev;
  for (long long i = (0), __last_i = (n); i < __last_i; i++)
    ev[-a[i]].push_back(i);
  vector<vector<long long>> nxt(M, vector<long long>(n + 1, n));
  for (auto&& e : ev) {
    for (auto&& x : e.second) {
      nxt[0][x] = min(nxt[0][x], seg.find(x + 1, n));
    }
    for (auto&& x : e.second) {
      seg.update(x, x);
    }
  }
  for (long long i = (1), __last_i = (M); i < __last_i; i++)
    for (long long j = (n)-1, __last_j = (0); j >= __last_j; j--) {
      nxt[i][j] = min(nxt[i - 1][nxt[i - 1][j]], nxt[i][j + 1]);
    }
  long long x = 0, ans = 1;
  for (long long i = (M)-1, __last_i = (0); i >= __last_i; i--) {
    if (nxt[i][x] < n) {
      x = nxt[i][x];
      ans += 1LL << i;
    }
  }
  cout << ans << endl;
}
