#include <bits/stdc++.h>
using namespace std;
long long int m[2 * 262144 / 2 + 1], lazy[2 * 262144 / 2 + 1];
long long int a[100002], pre_max[100002], n, steps[100002];
void update(long long int node, long long int start, long long int end,
            long long int i, long long int j, long long int val) {
  if (lazy[node] != 0) {
    m[node] += (end - start + 1) * lazy[node];
    if (start != end) {
      lazy[2 * node] += lazy[node];
      lazy[2 * node + 1] += lazy[node];
    }
    lazy[node] = 0;
  }
  if (i > end or j < start or start > end) {
    return;
  }
  if (start >= i and end <= j) {
    m[node] += (end - start + 1) * val;
    if (start != end) {
      lazy[2 * node] += val;
      lazy[2 * node + 1] += val;
    }
    return;
  }
  long long int mid = (start + end) / 2;
  update(2 * node, start, mid, i, j, val);
  update(2 * node + 1, mid + 1, end, i, j, val);
  m[node] = max(m[2 * node], m[2 * node + 1]);
  return;
}
long long int query(long long int node, long long int start, long long int end,
                    long long int i, long long int j) {
  if (lazy[node] != 0) {
    m[node] += (end - start + 1) * lazy[node];
    if (start != end) {
      lazy[2 * node] += lazy[node];
      lazy[2 * node + 1] += lazy[node];
    }
    lazy[node] = 0;
  }
  if (i > end or j < start or start > end) {
    return 0;
  }
  if (start >= i and end <= j) {
    return m[node];
  }
  long long int q1, q2, mid = (start + end) / 2;
  q1 = query(2 * node, start, mid, i, j);
  q2 = query(2 * node + 1, mid + 1, end, i, j);
  return (max(q1, q2));
}
void build_segment_tree(long long int node, long long int start,
                        long long int end) {
  m[node] = 0;
  lazy[node] = 0;
  if (start == end) return;
  long long int mid = (start + end) / 2;
  build_segment_tree(2 * node, start, mid);
  build_segment_tree(2 * node + 1, mid + 1, end);
}
inline void getNearestMax() {
  stack<long long int> s;
  s.push(a[1]);
  pre_max[0] = -1;
  pre_max[1] = -1;
  s.push(1);
  long long int count = 1, index = 2, top_index;
  while (!s.empty() and index <= n) {
    top_index = s.top();
    if (a[index] < a[top_index]) {
      pre_max[index] = top_index;
      s.push(index);
      index++;
      continue;
    }
    while (!s.empty()) {
      top_index = s.top();
      if (a[top_index] > a[index]) {
        break;
      }
      s.pop();
    }
    if (s.empty()) {
      pre_max[index] = -1;
      s.push(index);
    } else {
      pre_max[index] = s.top();
      s.push(index);
    }
    index++;
  }
}
int main() {
  cin >> n;
  long long int i;
  for (i = 1; i <= n; i++) {
    cin >> a[i];
  }
  getNearestMax();
  for (i = 1; i <= n; i++) {
  }
  steps[1] = 0;
  long long int pre_index = 1, ans = 0, temp_ans;
  build_segment_tree(1, 1, 262144 / 2);
  for (i = 2; i <= n; i++) {
    if (pre_max[i] == -1) {
      temp_ans = 0;
      update(1, 1, 262144 / 2, i, i, temp_ans);
      continue;
    }
    if (a[i - 1] > a[i]) {
      temp_ans = 1;
      update(1, 1, 262144 / 2, i, i, temp_ans);
    } else {
      temp_ans = query(1, 1, 262144 / 2, pre_max[i] + 1, i - 1) + 1;
      update(1, 1, 262144 / 2, i, i, temp_ans);
    }
    ans = max(ans, temp_ans);
  }
  cout << ans << endl;
}
