#pragma GCC optimize(2)
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
using namespace std;

#define ll long long
#define mp make_pair
#define pb push_back

#define eprintf(...) fprintf(stderr, __VA_ARGS__)

const int maxn = 1 << 19;
int mx[maxn << 1], siz;

inline int Max(int a, int b) {return a < b ? b : a;}

void init(int n) {
	for (siz = 1; siz < n; siz <<= 1) ;
	memset(mx, 0, sizeof(mx));
}

void upd(int i, int a, int b, int x, int v) {
	if (a + 1 == b) {mx[i] = v; return ;}
	int m = (a + b) >> 1;
	if (x < m) upd(i << 1, a, m, x, v);
	else upd(i << 1 | 1, m, b, x, v);
	mx[i] = Max(mx[i << 1], mx[i << 1 | 1]);
}

int qry(int i, int a, int b, int v, vector <int> &vec) {
	if (a + 1 == b) {vec.pb(a); return mx[i];}
	int m = (a + b) >> 1;
	if (v < mx[i << 1]) v = qry(i << 1, a, m, v, vec);
	if (v < mx[i << 1 | 1]) v = qry(i << 1 | 1, m, b, v, vec);
	return v;
}

struct T {
	int val, fix;
	T *ls, *rs;
	T(int v) {val = v; fix = rand(); ls = rs = NULL;}
};

void split(T *x, int v, T *&a, T *&b) {
	if (!x) {a = b = NULL; return ;}
	if (x->val <= v) a = x, split(x->rs, v, a->rs, b);
	else b = x, split(x->ls, v, a, b->ls);
}

T *merge(T *a, T *b) {
	if (!a || !b) return a ? a : b;
	if (a->fix < b->fix) {a->rs = merge(a->rs, b); return a;}
	else {b->ls = merge(a, b->ls); return b;}
}

int mxv(T *x) {if (x) while (x->rs) x = x->rs; return x ? x->val : 0;}
void prt(T *x) {if (x) prt(x->ls), printf("%d ", x->val), prt(x->rs);}

int n, a[maxn];
T *rt[maxn];
int lst[maxn];

int main() {
//	freopen("in", "r", stdin);
	srand(200);
	scanf("%d", &n);
	for (int i = 0; i < n; ++ i) scanf("%d", &a[i]);
//	n = 2e5;
//	for (int i = 0; i < n; ++ i) a[i] = n - i;
	int m = 0;
	for (int i = 0; i < n; ++ i) {
		if (a[i] < a[i - 1]) m ++;
		rt[m] = merge(rt[m], new T(a[i])); lst[m] = a[i];
	}
	int n2 = n + m; init(n2);
	for (int i = 0; i <= m; ++ i) upd(1, 0, n2, i, lst[i]);
	int nw = n;
	for (int i = 0; i <= n; ++ i) {
		vector <int> vec;
		qry(1, 0, n2, 0, vec);
		++ m;
		int v = 0;
		for (int j = 0; j < vec.size(); ++ j) {
			T *a, *b;
			split(rt[vec[j]], v, a, b);
			rt[vec[j]] = a;
			upd(1, 0, n2, vec[j], mxv(a));
			v = mxv(b);
			rt[m] = merge(rt[m], b);
		}
		while (nw && mxv(rt[m]) == nw) {
			T *d; split(rt[m], nw - 1, rt[m], d); -- nw;
		}
		if (!nw) {printf("%d\n", i); break;}
		if (rt[m]) upd(1, 0, n2, m, mxv(rt[m]));
		else -- m;
//		for (int j = 0; j <= m; ++ j)
//			prt(rt[j]); puts("");
	}
//	printf("%.3f\n", clock() * 1.0 / CLOCKS_PER_SEC);
	return 0;
}
