#include <bits/stdc++.h>
#include <iomanip>
#define DEBUG 1

using namespace std;

typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef pair<LD, LD> PLDLD;
typedef vector<int> VI;
typedef vector<LL> VLL;
typedef vector<char> VB;

#define FOR(i,a,b) for(int i=(a);i<(int)(b);++i)
#define REP(i,n) FOR(i,0,n)
#define CLR(a) memset((a), 0 ,sizeof(a))
#define ALL(a) a.begin(),a.end()
#define UNQ(a) a.erase(std::unique(ALL(a)),a.end());
#define endl "\n"

const LD EPS=1e-5;
const long long INFLL=(LL)(1e9)*(LL)(1e9);
const int INF=1e9+7;

template<class T>
void chmin(T& a, const T b)
{
	if(a>b)
		a=b;
}
template<class T>
void chmax(T& a, const T b)
{
	if(a<b)
		a=b;
}

const LL powLL(const LL p, const LL q)
{
	LL t=1;
	for(int i=0;i<q;i++)
		t*=p;
	return t;
}

template <typename T>
struct has_iter
{
	private:
		template <typename U>
		static constexpr true_type check(typename U::iterator*);
		template <typename U>
		static constexpr false_type check(...);

	public:
		static constexpr bool value = decltype(check<T>(nullptr))::value;
};


template<typename T, typename U = typename T::iterator>
void print(const T& container)
{
		auto&& first=begin(container), last=end(container);
		auto&& back=prev(last);
		for(auto e=first; e!=last; e=next(e))
			cout<<*e<<" \n"[e==back];
}


extern void* enabler;
template<typename Head, typename enable_if<!has_iter<Head>::value>::type*& = enabler>
void print(const Head& head)
{
	cout<<head<<endl;
}

template<> void print<string>(const string& container)
{
	cout<<container<<endl;
}

template<typename Head, typename... Tail>
void print(const Head& head, const Tail&... tail)
{
	cout<<head<<" ";
	print(tail...);
}

template<typename... Args>
void printd(const Args&... args)
{
	#ifdef DEBUG
		print(args...);
	#endif
}

template<typename Head>
void input(Head& head)
{
	cin>>head;
}

template<typename Head, typename... Tail>
void input(Head& head, Tail&... tail)
{
	cin>>head;
	input(tail...);
}

void io_speedup()
{
	cin.tie(0);
	cout.tie(0);
	ios::sync_with_stdio(false);
}

template<typename T>
istream& operator >> (istream& is, vector<T>& vec)
{
	for(T& x: vec) is >> x;
	return is;
}


template<typename T, typename U>
istream& operator >> (istream& is, pair<T, U>& t)
{
	is>>t.first>>t.second;
	return is;
}

template<int N, typename... Ts, typename enable_if<N == sizeof...(Ts)-1>::type*& = enabler>
void tuple_in(istream &is, tuple<Ts...> &t)
{
	is>>get<N>(t);
}
template<int N, typename... Ts, typename enable_if<N < sizeof...(Ts)-1>::type*& = enabler>
void tuple_in(istream &is, tuple<Ts...> &t)
{
	is>>get<N>(t);
	tuple_in<N+1, Ts...>(is, t);
}

template<typename... Ts>
istream& operator >> (istream& is, tuple<Ts...>& t)
{
	tuple_in<0, Ts...>(is, t);
	return is;
}


template<typename T, typename U>
ostream& operator << (ostream& os, const pair<T, U>& t)
{
	os<<'('<<t.first<<", "<<t.second<<')';
	return os;
}

template<int N, typename... Ts, typename enable_if<N == sizeof...(Ts)-1>::type*& = enabler>
void tuple_out(ostream &os,const tuple<Ts...> &t)
{
	os<<get<N>(t);
}
template<int N, typename... Ts, typename enable_if<N < sizeof...(Ts)-1>::type*& = enabler>
void tuple_out(ostream &os,const tuple<Ts...> &t)
{
	os<<get<N>(t)<<", ";
	tuple_out<N+1, Ts...>(os, t);
}

template<typename... Ts>
ostream& operator << (ostream& os, const tuple<Ts...>& t)
{
	os<<'(';
	tuple_out<0, Ts...>(os, t);
	os<<')';
	return os;
}

template<typename T>
vector<T> read(int n)
{
	vector<T> t(n);
	cin>>t;
	return t;
}

template<typename T>
T read()
{
	T t;
	cin>>t;
	return t;
}

template<typename Head, typename... Tail>
struct vector_demensions
{
	using type=vector<typename vector_demensions<Tail...>::type>;
};

template<typename Head>
struct vector_demensions<Head> { using type=Head; };

template<typename T>
vector<T> make_vectors(int size, T val)
{
	return vector<T>(size, val);
}

template<typename T=int, typename... Args>
auto make_vectors(int size, Args... tail)
	-> typename vector_demensions<Args..., T>::type
{
	auto val=make_vectors<T>(forward<Args>(tail)...);
	return vector<decltype(val)>(size, val);
}


struct Edge
{
	int from,to,cost,rev;
};
class FlowNetwork
{
    public:
        FlowNetwork(int n):graph(vector<vector<Edge>>(n)),used(vector<char>(n))
        {}
        void add_Edge(int from, int to, int cap);
        void add_Edge_nd(int from, int to, int cap);
        int ford_fulkerson(int from, int to);

    private:
        vector<vector<Edge>> graph;
        vector<char> used;
        int dfs(int from, int to, int cap);
};
void FlowNetwork::add_Edge(int from, int to, int cap)
{
	graph[from].push_back((Edge){from,to,cap,(int)graph[to].size()});
	graph[to].push_back((Edge){to,from,0,(int)graph[from].size()-1});
}
void FlowNetwork::add_Edge_nd(int from, int to, int cap)
{
	graph[from].push_back((Edge){from,to,cap,(int)graph[to].size()});
	graph[to].push_back((Edge){to,from,cap,(int)graph[from].size()-1});
}
int FlowNetwork::dfs(int from, int to, int f)
{
	if(from == to) return f;
	int d;
	used[from]=true;
	for(int i=0;i<graph[from].size();i++)
	{
		Edge &e=graph[from][i];
		if(used[e.to] || e.cost<=0) continue;
		d = dfs(e.to, to, min(e.cost, f));
		if(d>0)
		{
			e.cost -= d;
			graph[e.to][e.rev].cost += d;
			return d;
		}
	}
	return 0;
}
int FlowNetwork::ford_fulkerson(int from, int to)
{
	int flow=0;
	while(1)
	{
        fill(used.begin(),used.end(),0);
		int f=dfs(from,to,INF);
		if(f==0)break;
		flow += f;
	}
	return flow;
}


class UnionFind
{
    private:
        vector<int> parent;

    public:
        UnionFind(const int n):parent(vector<int>(n,-1))
        {}
        
        const int Find(const int p)
        {
            return parent[p] < 0 ? p : parent[p] = Find(parent[p]);
        }
        const void Merge(int p, int q);

        const bool Belong(const int p, const int q)
        {
            return Find(p) == Find(q);
        }
        const int GetSize(const int p)
        {
            return -parent[Find(p)];
        }
};

const void UnionFind::Merge(int p, int q)
{
    p=Find(p);
    q=Find(q);
    if(p==q) return;
    if(parent[p] < parent[q])
    {
        parent[p] += parent[q];
        parent[q]=p;
    }
    else
    {
        parent[q] += parent[p];
        parent[p]=q;
    }
}



int main()
{
	int n;
	cin>>n;
	auto a(read<int>(n));

	auto f=[&](int d)
	{
		vector<PII> let;
		let.push_back(PII(0,-1));
		REP(i,n)
		{
			int p,q;
			tie(p,q)=let[let.size()-1];
			if(p<a[i])
				let.push_back(PII(a[i],0));
			else
			{
				while(let[let.size()-1].first>=a[i])
				{
					tie(p,q)=let[let.size()-1];
					let.pop_back();
				}

				if(q+1>=d)
				{
					while(q+1>=d)
					{
						tie(p,q)=let[let.size()-1];
						let.pop_back();
						if(q==-1) return false;
					}
					if(let[let.size()-1].first<p-1)
						let.emplace_back(p-1, q);
					let.emplace_back(p, q+1);
					let.push_back(PII(a[i],0));
				}
				else
				{
					if(let[let.size()-1].first<a[i]-1)
						let.emplace_back(a[i]-1, q);
					let.emplace_back(a[i], q+1);
				}
			}
		}
		return true;
	};

	int mi=0,ma=INF,mid;
	while(ma>mi+1)
	{
		mid=(ma+mi)/2;
		if(f(mid))
			ma=mid;
		else
			mi=mid;
	}
	print(ma);
}

Measured memory_bytes: 4692