#pragma GCC optimize("Ofast")
#include <cassert>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
using std::cin; using std::cout;
using std::endl;
using std::bitset; using std::map;
using std::queue; using std::priority_queue;
using std::set; using std::string;
using std::stringstream; using std::vector;
using std::pair; using std::make_pair;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef pair<ULL, ULL> puu;
#ifdef DEBUG
using std::cerr;
#define pass cerr << "[" << __FUNCTION__ << "] : line = " << __LINE__ << endl;
#define display(x) cerr << #x << " = " << x << endl;
#define displaya(a, st, n)                                                     \
  {                                                                            \
    cerr << #a << " = {";                                                      \
    for (int qwq = (st); qwq <= (n); ++qwq)                                    \
      if (qwq == (st))                                                         \
        cerr << a[qwq];                                                        \
      else                                                                     \
        cerr << ", " << a[qwq];                                                \
    cerr << "}" << endl;                                                       \
  }
#define displayv(a) displaya(a, 0, (int)(a.size() - 1))
#include <ctime>
class MyTimer {
    clock_t st;
public:
    MyTimer() { cerr << std::fixed << std::setprecision(0); reset(); }
    ~MyTimer() { report(); }
    void reset() { st = clock_t(); }
    void report() {  cerr << "Time consumed: " << (clock() - st) * 1e3 / CLOCKS_PER_SEC << "ms" << endl; }
} myTimer;
#else
#define cerr if(false) std::cout
#define pass ;
#define display(x) ;
#define displaya(a, st, n) ;
#define displayv(a) ;
class MyTimer {
public: void reset() {} void report() {}
} myTimer;
#endif

template<typename A, typename B>
std::ostream& operator << (std::ostream &cout, const pair<A, B> &x) {
    return cout << "(" << x.first << ", " << x.second << ")";
}
template<typename T1, typename T2>
inline bool chmin(T1 &a, const T2 &b) { return a > b ? a = b, true : false; }
template<typename T1, typename T2>
inline bool chmax(T1 &a, const T2 &b) { return a < b ? a = b, true : false; }
inline int readint() {
    int a = 0; char c = getchar(), p = 0;
    while(isspace(c)) c = getchar();
    if(c == '-') p = 1, c = getchar();
    while(isdigit(c)) a = a*10 + c - '0', c = getchar();
    return p ? -a : a;
}

const int maxN = 200000 + 233;
const int maxA = 1000000000 + 233;
int n, a[maxN];
int s[maxN];

const int NODE = maxN * 30 * 8;
int cnt = 0;
int val[NODE], lson[NODE], rson[NODE];
int ql, qr;
void pushdown(int o) {
    if(val[o]) {
        if(lson[o] == 0) lson[o] = ++cnt;
        if(rson[o] == 0) rson[o] = ++cnt;
        val[lson[o]] = val[rson[o]] = val[o];
        val[o] = 0;
    }
}
void cover(int &o, int L, int R) {
    if(o == 0) o = ++cnt;
    if(ql <= L && R <= qr) {
        val[o] = 1;
    } else {
        int M = (L + R) >> 1;
        pushdown(o);
        if(ql <= M) cover(lson[o], L, M);
        if(qr > M) cover(rson[o], M + 1, R);
    }
}
int qpos, qval;
int query(int o, int L, int R) {
    if(val[o]) return val[o];
    int M = (L + R) >> 1;
    if(qpos <= M) return query(lson[o], L, M);
    else return query(rson[o], M + 1, R);
}
void modify(int &o, int L, int R) {
    if(o == 0) o = ++cnt;
    if(L == R) {
        val[o] = qval;
    } else {
        int M = (L + R) >> 1;
        pushdown(o);
        if(qpos <= M) modify(lson[o], L, M);
        else modify(rson[o], M + 1, R);
    }
}
int rt = 1;
void cover(int l, int r) {
    ql = l; qr = r; cover(rt, 1, maxA);
}
int query(int p) {
    qpos = p; return query(rt, 1, maxA);
}
void modify(int p, int val) {
    qpos = p; qval = val; modify(rt, 1, maxA);
}

bool check(int sus) {
//    printf("sus = %d\n", sus);
    for(int i = 0; i <= cnt; ++i) lson[i] = rson[i] = val[i] = 0;
    cnt = 1;
    cover(1, maxA);
    for(int i = 2; i <= n; ++i) {
//        display(i);
        if(a[i] > a[i - 1]) {
            ql = a[i - 1] + 1; qr = a[i];
            cover(rt, 1, maxA);
        } else {
            int p = a[i];
            while(p >= 1 && query(p) == sus) --p;
            if(p == 0) return false;
            modify(p, query(p) + 1);
            for(int j = p + 1; j <= a[i]; ++j) modify(j, 1);
        }
    }
    return true;
}

bool spj() {
    for(int i = 2; i <= n; ++i)
        if(a[i] <= a[i - 1]) return false;
    return true;
}

int main() {
    n = readint();
    for(int i = 1; i <= n; ++i) a[i] = readint();
    if(spj()) {
        printf("1\n"); return 0;
    }
    int L = 2, R = n;
    while(L < R) {
        int M = (L + R) >> 1;
        if(check(M)) R = M; else L = M + 1;
    }
    printf("%d\n", L);
    return 0;
}

Measured memory_bytes: 64512