#include <bits/stdc++.h>
#include <boost/range/irange.hpp>

using namespace std;
using namespace boost;

// Segment Tree
struct ST {
    ST(int64_t n)
     : n(n), cap(pow(2, int64_t(log2(n - 1)) + 1)), value(2 * cap - 1, int64_t(-1)) {}

    bool is_root(int64_t idx) const {
        return idx == 0;
    }

    bool has_children(int64_t idx) const {
        return right(idx) < value.size();
    }

    int64_t parent(int64_t idx) const {
        return (idx - 1) / 2;
    }

    int64_t left(int64_t idx) const {
        return 2 * idx + 1;
    }

    int64_t right(int64_t idx) const {
        return 2 * idx + 2;
    }

    int64_t leaf(int64_t idx) const {
        return cap - 1 + idx;
    }

    void range_update(int64_t a, int64_t b, int64_t v, int64_t v2 = -1, int64_t cur = 0, int64_t l = 0, int64_t r = -1) {
        if (r == -1) {
            r = cap;
        }

        if (r <= a || b <= l) {
            if (v2 >= 0) {
                value[cur] = v2;
            }
            return;
        }

        if (a <= l && r <= b) {
            value[cur] = v;
            return;
        }

        if (v2 < 0) {
            v2 = value[cur];
        }

        range_update(a, b, v, v2, left(cur), l, (l + r) / 2);
        range_update(a, b, v, v2, right(cur), (l + r) / 2, r);

        value[cur] = -1;
    }

    int64_t get(int64_t a, int64_t cur = 0, int64_t l = 0, int64_t r = -1) {
        if (r == -1) {
            r = cap;
        }

        if (r <= a || a < l) {
            return -1;
        }

        if (value[cur] >= 0) {
            return value[cur];
        }

        int64_t vl = get(a, left(cur), l, (l + r) / 2);
        if (vl >= 0) {
            return vl;
        }

        int64_t vr = get(a, right(cur), (l + r) / 2, r);
        return vr;
    }

    int64_t n;
    int64_t cap;
    vector<int64_t> value;
};



main() {
    int64_t n;
    cin >> n;

    // len
    vector<int64_t> a;
    int64_t prev = (1L << 30);
    int64_t m = 0;
    for (auto i : irange(0L, n)) {
        int64_t aa;
        cin >> aa;
        aa = min(aa, 200000L);
        if (prev >= aa) {
            a.push_back(aa);
            m = max(aa, m);
        }

        prev = aa;
    }

    auto r = irange(1L, static_cast<int64_t>(a.size()) + 1L);
    auto it = partition_point(r.begin(), r.end(), [&a, m](int64_t t){
        ST tree(m + 1);

        tree.range_update(0, a[0], 0);
        // prev len
        int64_t s = a[0];
        for (int64_t i_block = 1; i_block < a.size(); ++i_block) {
            auto len = a[i_block];

            if (s < len) {
                tree.range_update(s, len, 0);
            }

            s = len;

            bool found = false;
            for (auto i = s - 1; i >= 0; --i) {
                auto v = tree.get(i);
                if (v + 1 < t) {
                    tree.range_update(i, i + 1, v + 1);
                    if (i + 1 != s) {
                        tree.range_update(i + 1, s, 0);
                    }
                    found = true;
                    break;
                }
            }

            if (!found) {
                return true;
            }
        }

        return false;
    });

    cout << *it << endl;
}

Measured memory_bytes: 6000