#include                        <bits/stdc++.h>
#define   lli                   unsigned long long int
#define   ll                    long long int
#define   PI                    acos(-1.0)
#define   UNIQUE(V)             (V).erase(unique(ALL(V), (V).end()) //vector/string etc must need to be sorted
#define   timesave              ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define   ALL(V)                (V).begin(), (V).end()
#define   MEMSET(a, val)        memset(a, val, sizeof(a))
using     namespace             std;

template  <class T> T GCD(T a, T b) { return (b != 0 ? GCD <T> (b, a%b) : a); }
template  <class T> T LCM(T a, T b) { return ((a*b)  / GCD <T> (a, b)); }

const int M = 1e6+5;
int PRIME[M];
int b[2*M];

void P()
{
    for(int i = 2; i*i <= 1e6; i++){
        if(PRIME[i] == 0){
            for(int j = 2*i; j <= 1e6; j += i) PRIME[j] = 1;
        }
    }
}

int main()
{
//  ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
//  freopen("input.txt", "r", stdin);
//  freopen("output.txt", "w", stdout);

    timesave;

    //while(1){

    P();

    int t, n;

    cin >> t;

    while(t--){
        cin >> n;

       // memset(b, 0, sizeof(b));

        int a[n+5], val, cnt = 0, d1, d2;

        for(int i = 0; i < n; i++) {cin >> a[i]; b[a[i]] = 1;}

        sort(a, a+n);

        if(n == 1){
            val = a[0]*a[0];
            if(PRIME[a[0]] == 0) cout << val << endl;
            else cout << -1 << endl;
            continue;
        }
        else val = a[0] * a[n-1];

        //cout << val << endl;

        for(int i = 1; i*i <= val; i++){
            if(i == 1 || i == val) continue;

            if(val%i == 0){
                d1 = i; d2 = val/i;
                if(b[d1] == 0 || b[d2] == 0) {break;}
                else if(d1 != d2) cnt += 2;
                else cnt++;
            }
        }

        if(cnt == n) cout << val << endl;
        else cout << -1 << endl;
    }

    //}

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define ff first
#define ss second
#define all(x) (x).begin(), (x).end()
typedef int64_t lld;
typedef pair<int, int> pii;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, pair<T1, T2> p){
	return out << '(' << p.ff << ", " << p.ss << ')';
}

vector<int> v, lis, dlisl;
set<pii> curs, dcurs;

int calc(int n){
	int ans = INT_MAX;
	for(int i = 1; i <= n; i++){
		fill(all(lis), 0); curs.clear(); curs.insert({INT_MIN, 0});
		for(int j = 1, a = 0; j <= n; j++){
			if(j == i)a++;
			else
			lis[j] = lis[prev(curs.lower_bound({v[j]+a, INT_MAX}))->ss]+1,
			curs.insert({v[j]+a, j});
		}
		ans = min(ans, n-1-*max_element(all(lis)));
		//cout << n-1-*max_element(all(lisl)) << endl;
	}
	return ans;
}

signed main(){
	int n = 5;
	cin >> n;
	v.pb(0);
	srand(time(0));
	for(int i = 0; i < n; i++){
		int a = rand()%10+1;
		cin >> a;
		//cout << a << " ";
		v.pb(a);
	}//cout << endl;
	lis.pb(v[0]);
	for(int i = 1; i < n; i++){
		if(v[i] > lis.back())lis.pb(v[i]);
		else *lower_bound(all(v), v[i]) = v[i];
	}
	cout << n-1-lis.size() << endl;
	//cout << calc(n) << endl;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define ff first
#define ss second
#define all(x) (x).begin(), (x).end()
typedef int64_t lld;
typedef pair<int, int> pii;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, pair<T1, T2> p){
	return out << '(' << p.ff << ", " << p.ss << ')';
}

vector<int> v, lisl;
set<pii> curs;
signed main(){
	int n;
	cin >> n;
	v.pb(0);
	for(int i = 0; i < n; i++){
		int a;
		cin >> a;
		v.pb(a-i);
	}
	lisl.resize(n+1); curs.insert({INT_MIN, 0});
	for(int i = 1; i <= n; i++){
		lisl[i] = lisl[prev(curs.lower_bound((pii){v[i], INT_MAX}))->ss]+1;
		curs.insert({v[i], i});
	}
	cout << max(0, n-1-*max_element(all(lisl))) << endl;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define ff first
#define ss second
#define all(x) (x).begin(), (x).end()
typedef int64_t lld;
typedef pair<int, int> pii;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, pair<T1, T2> p){
	return out << '(' << p.ff << ", " << p.ss << ')';
}

vector<int> v, lisl, dlisl;
set<pii> curs, dcurs;
signed main(){
	int n;
	cin >> n;
	v.pb(0);
	for(int i = 0; i < n; i++){
		int a;
		cin >> a;
		v.pb(a-i);
	}
	lisl.resize(n+1); dlisl.resize(n+1); curs.insert({INT_MIN, 0}), dcurs.insert({INT_MIN, 0});
	for(int i = 1; i <= n; i++){
		lisl[i] = lisl[prev(curs.lower_bound({v[i], INT_MAX}))->ss]+1;
		dlisl[i] = max(lisl[prev(curs.lower_bound({v[i]+1, INT_MAX}))->ss], dlisl[prev(dcurs.lower_bound({v[i]+1, INT_MAX}))->ss])+1;
		curs.insert({v[i], i});
		dcurs.insert({v[i]+1, i});
	}
	cout << min(n-*max_element(all(dlisl)), n-1-*max_element(all(lisl))) << endl;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define ff first
#define ss second
#define all(x) (x).begin(), (x).end()
typedef int64_t lld;
typedef pair<int, int> pii;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, pair<T1, T2> p){
	return out << '(' << p.ff << ", " << p.ss << ')';
}

template<typename It>
ostream& outIt(ostream& out, It b, It e){
	for(It i = b; i != e; i++)
		out << (i==b?"":" ") << *i;
	return out;
}

template<typename T>
ostream& operator<<(ostream& out, vector<T>& v){
	return outIt(out << '[', all(v)) << ']';
}

vector<int> v, lis, dlis;
set<pii> curs, dcurs;

int calc(int n){
	int ans = INT_MAX;
	for(int i = 1; i <= n; i++){
		fill(all(lis), 0); curs.clear(); curs.insert({INT_MIN, 0});
		for(int j = 1, a = 0; j <= n; j++){
			if(j == i)a++;
			else
			lis[j] = lis[prev(curs.lower_bound({v[j]+a, INT_MAX}))->ss]+1,
			curs.insert({v[j]+a, j});
		}
		ans = min(ans, n-1-*max_element(all(lis)));
		//cout << n-1-*max_element(all(lisl)) << endl;
	}
	return ans;
}

signed main(){
	int n = 5;
	cin >> n;
	srand(time(0));
	for(int i = 0; i < n; i++){
		int a = rand()%10+1;
		cin >> a;
		//cout << a-i << " ";
		v.pb(a-i);
	}
	//cout << endl;
	for(int i = 0; i < n; i++){
		if(dlis.empty()) dlis.pb(v[0]+1);
		else if(v[i]+1 >= dlis.back()) dlis.pb(v[i]+1);
		else *upper_bound(all(dlis), v[i]+1) = v[i]+1;
		//cout << lis << dlis <<endl;
		if(i != n-1){
			int x = upper_bound(all(lis), v[i+1]+1)-lis.begin();
			//cout << x <<endl;
			//assert(x == 0 || dlis[x-1] <= v[i+1]+1);
			if(x == dlis.size())dlis.pb(v[i+1]+1);
			else dlis[x] = min(dlis[x], v[i+1]+1);
		}
		//cout << lis << dlis <<endl;
		if(lis.empty()) lis.pb(v[0]);
		else if(v[i] >= lis.back()) lis.pb(v[i]);
		else *upper_bound(all(lis), v[i]) = v[i];
		//cout << lis << dlis <<endl << endl;
	}
	cout << max(0, min(n-(int)dlis.size(), n-1-(int)lis.size())) << endl;
	//cout << calc(n) << endl;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define ff first
#define ss second
#define all(x) (x).begin(), (x).end()
typedef int64_t lld;
typedef pair<int, int> pii;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, pair<T1, T2> p){
	return out << '(' << p.ff << ", " << p.ss << ')';
}

vector<int> v, lisl, dlisl;
set<pii> curs, dcurs;
signed main(){
	int n;
	cin >> n;
	v.pb(0);
	for(int i = 0; i < n; i++){
		int a;
		cin >> a;
		v.pb(a-i);
	}
	lisl.resize(n+1); dlisl.resize(n+1); curs.insert({INT_MIN, 0}), dcurs.insert({INT_MIN, 0});
	for(int i = 1; i <= n; i++){
		lisl[i] = lisl[prev(curs.lower_bound({v[i], INT_MAX}))->ss]+1;
		if(i != n)dlisl[i+1] = lisl[prev(curs.lower_bound({v[i+1]+1, INT_MAX}))->ss]+1;
		if(dcurs.size())dlisl[i] = max(dlisl[i], dlisl[prev(dcurs.lower_bound({v[i]+1, INT_MAX}))->ss]+1);
		curs.insert({v[i], i});
		if(i != 1)dcurs.insert({v[i]+1, i});
	}
	cout << min(n-*max_element(all(dlisl)), n-1-*max_element(all(lisl))) << endl;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define ff first
#define ss second
#define all(x) (x).begin(), (x).end()
typedef int64_t lld;
typedef pair<int, int> pii;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, pair<T1, T2> p){
	return out << '(' << p.ff << ", " << p.ss << ')';
}

vector<int> v, lisl, dlisl;
set<pii> curs, dcurs;
signed main(){
	int n;
	cin >> n;
	v.pb(0);
	for(int i = 0; i < n; i++){
		int a;
		cin >> a;
		v.pb(a-i);
	}
	lisl.resize(n+1); dlisl.resize(n+1); curs.insert({INT_MIN, 0}), dcurs.insert({INT_MIN, 0});
	for(int i = 1; i <= n; i++){
		lisl[i] = lisl[prev(curs.lower_bound((pii){v[i], INT_MAX}))->ss]+1;
		dlisl[i] = max(lisl[prev(curs.lower_bound((pii){v[i]+1, INT_MAX}))->ss], dlisl[prev(dcurs.lower_bound((pii){v[i]+1, INT_MAX}))->ss])+1;
		curs.insert({v[i], i});
		dcurs.insert({v[i]+1, i});
	}
	cout << max(0, n-1-*max_element(all(dlisl))) << endl;
}


#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
int main() {
	int n, c = 0;
	vi lis;
	cin >> n;
	for(int t, i = 0; i < n; i++) {
		cin >> t;
		t-=i;
		auto it = lower_bound(lis.begin(), lis.end(), t);
		if(it==lis.end()) lis.push_back(t);
		else if(*it==t&&++it==lis.end()) lis.push_back(t);
		else *it = t;
//		for(auto i : lis) cout << i << " "; cout << "\n";
	}
	cout << max(0, n-(int)lis.size()-1);
}


#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
int main() {
	int n, c = 0;
	vi lis, lit;
	cin >> n;
	for(int t, i = 0; i < n; i++) {
		cin >> t;
		auto it = lower_bound(lit.begin(), lit.end(), t);
		if(it!=lit.end()) *it = t;
		else lit.push_back(t);
		t-=i;
		it = upper_bound(lis.begin(), lis.end(), t);
		if(it!=lis.end()) *it = t;
		else lis.push_back(t);
	}
	cout << max(0, n-(int)lit.size()-1);
}


#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
int main() {
	int n, c = 0;
	vi lis;
	cin >> n;
	for(int t, i = 0; i < n; i++) {
		cin >> t;
		t-=i;
		auto it = lower_bound(lis.begin(), lis.end(), t+1);
		if(it!=lis.end()) *it = t;
		else lis.push_back(t);
	}
	cout << max(0, n-(int)lis.size()-1);
}


#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
int main(){
int n;cin >> n;
vi a;
for(int t,i = 0; i < n; i++)  {
cin >> t;t-=i;
auto it = lower_bound(a.begin(),
a.end(), t);
if(it==a.end()) a.push_back(t);
else *it = t;
}
int ans = n - a.size();
if(ans) ans--;
cout << ans;
}


#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
int main(){
int n;cin >> n;
vi a;
for(int t,i = 0; i < n; i++)  {
cin >> t;t-=i;
auto it = upper_bound(a.begin(),
a.end(), t);
if(it==a.end()) a.push_back(t);
else *it = t;
}
int ans = n - a.size();
if(ans) ans--;
cout << ans;
}


#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
int main() {
	int n;
	vi lis;
	cin >> n;
	for(int t, i = 0; i < n; i++) {
		cin >> t,t-=i;
		auto it = upper_bound(lis.begin(), lis.end(), t);
		if(it!=lis.end()) *it = t;
		else lis.push_back(t);
	}
	cout << max(0, n-(int)lis.size()-1);
}


#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
int main() {
	int n, c = 0;
	vi lis, lit;
	cin >> n;
	for(int t, i = 0; i < n; i++) {
		cin >> t;
		t-=i;
		auto it = lower_bound(lis.begin(), lis.end(), t+1);
		if(it!=lis.end()) *it = t;
		else lis.push_back(t);
	}
	cout << max(0, n-(int)lit.size()-1);
}


#include<bits/stdc++.h>
#define pb push_back
using namespace std;
using vi = vector<int>;
int n, c = 0;
vi x, y;
vector<pair<int, int>> b;
int main() {
	cin >> n;
	for(int t, i = 0; i < n; i++) {
		cin >> t, t -= i;
		auto it = upper_bound(x.begin(), x.end(), t);
		int p = it-x.begin();
		if(it==x.end()) x.pb(t);
		else *it = t;
		++t;
		it = upper_bound(y.begin(), y.end(), t);
		if(it==y.end()) y.pb(t);
		else *it = t;
		if(i) {
			if(y.size() < b.back().first)
				y.pb(b.back().second);
			else
				y[b.back().first] = min(y[b.back().first], b.back().second);
		}
		b.pb({p, t-1});
	}
	cout << max(0, n - (int)max(x.size(), y.size()) - 1);
}


#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
int main() {
	int n, c = 0;
	vi lis, lit;
	cin >> n;
	for(int p = -1, t, i = 0; i < n; i++) {
		cin >> t;
		auto it = lower_bound(lit.begin(), lit.end(), t);
		if(it!=lit.end()) *it = t;
		else lit.push_back(t);
		t-=i;
		it = upper_bound(lis.begin(), lis.end(), t);
		if(it!=lis.end()) *it = t;
		else lis.push_back(t);
		if(n>100&&lis.size()!=lit.size()) {
			cout << p << " " << t << "\n";
		}
		p = t;
	}
	cout << max(0, n-(int)lis.size()-1);
}


#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
int main() {
	int n, c = 0;
	vi lis, lit;
	cin >> n;
	for(int t, i = 0; i < n; i++) {
		cin >> t;
		auto it = lower_bound(lit.begin(), lit.end(), t);
		if(it!=lit.end()) *it = t;
		else lit.push_back(t);
		t-=i;
		it = upper_bound(lis.begin(), lis.end(), t);
		if(it!=lis.end()) *it = t;
		else lis.push_back(t);
	}
	if(n>100) {
		cout << lis.size() << " " << lit.size() << "\n";
	}
	cout << max(0, n-(int)lis.size()-1);
}


#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
int main() {
	int n, c = 0;
	vi lis;
	cin >> n;
	for(int t, i = 0; i < n; i++) {
		cin >> t;
		t-=i;
		auto it = upper_bound(lis.begin(), lis.end(), t);
		if(it==lis.end()) lis.push_back(t);
		else *it = t;
	}
	cout << max(0, n-(int)lis.size()-1);
}


#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
int main() {
	int n;
	vi lis;
	cin >> n;
	for(int t, i = 0; i < n; i++) {
		cin >> t,t-=i;
		if(n>100) assert(t==6);
		auto it = upper_bound(lis.begin(), lis.end(), t);
		if(it!=lis.end()) *it = t;
		else lis.push_back(t);
	}
	cout << max(0, n-(int)lis.size()-1);
}


#include <bits/stdc++.h>
using namespace std;

class Node {
public:
    Node(int x) : x(x) {}

    void update(int l, int r, int pos, int val) {
        if (l + 1 == r) {
            x = val;
        } else {
            int m = (l + r) / 2;
            if (pos < m) {
                if (left == nullptr)
                    left = new Node(0);
                left->update(l, m, pos, val);
            } else {
                if (right == nullptr)
                    right = new Node(0);
                right->update(m, r, pos, val);
            }
            x = 0;
            if (left)
                x = std::max(x, left->x);
            if (right)
                x = std::max(x, right->x);
        }
    }

    int maximum(int l, int r, int rl, int rr) {
        if (rr <= l || rl >= r)
            return 0;
        if (rl <= l && r <= rr)
            return x;
        int m = (l + r) / 2;
        int res = 0;
        if (left)
            res = std::max(res, left->maximum(l, m, rl, rr));
        if (right)
            res = std::max(res, right->maximum(m, r, rl, rr));
        return res;
    }

    int x;
    Node* left = nullptr;
    Node* right = nullptr;
};

class ImplicitSegmentTree {
public:
    ImplicitSegmentTree(int n) : n(n), root(new Node(0)) {}

    void update(int pos, int val) {
        root->update(0, n, pos, val);
    }

    int maximum(int l, int r) {
        return root->maximum(0, n, l, r);
    }

private:
    int n;
    Node* root = nullptr;
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        a[i] += n - i;
    }

    const int INF = 1'500'000'001;
    ImplicitSegmentTree left(INF);
    vector<int> l_ws, l_cnts;
    for (int i = 0; i < n; i++) {
        // delete i
        int l_w = 0;
        int l_cnt = 0;
        if (i) {
            l_w = a[i-1];
            l_cnt = 1 + left.maximum(0, l_w + 1);
            left.update(l_w, l_cnt);
        }
        l_ws.push_back(l_w);
        l_cnts.push_back(l_cnt);
    }

    int best = 0;

    ImplicitSegmentTree right(INF);
    for (int i = n-1; i >= 0; i--) {
        // delete i
        if (i == n-1) {
            best = max(best, l_cnts[i]);
        } else {
            int x = right.maximum(l_ws[i], INF);
            best = max(best, l_cnts[i] + x);
        }
        right.update(a[i] + 1, right.maximum(a[i] + 1, INF) + 1);
    }

    cout << n - (1 + best) << endl;
}


#include <bits/stdc++.h>
using namespace std;

class Node {
public:
    Node(int x) : x(x) {}

    void update(int l, int r, int pos, int val) {
        if (l + 1 == r) {
            x = val;
        } else {
            int m = (l + r) / 2;
            if (pos < m) {
                if (left == nullptr)
                    left = new Node(0);
                left->update(l, m, pos, val);
            } else {
                if (right == nullptr)
                    right = new Node(0);
                right->update(m, r, pos, val);
            }
            x = 0;
            if (left)
                x = std::max(x, left->x);
            if (right)
                x = std::max(x, right->x);
        }
    }

    int maximum(int l, int r, int rl, int rr) {
        if (rr <= l || rl >= r)
            return 0;
        if (rl <= l && r <= rr)
            return x;
        int m = (l + r) / 2;
        int res = 0;
        if (left)
            res = std::max(res, left->maximum(l, m, rl, rr));
        if (right)
            res = std::max(res, right->maximum(m, r, rl, rr));
        return res;
    }

    int x;
    Node* left = nullptr;
    Node* right = nullptr;
};

class ImplicitSegmentTree {
public:
    ImplicitSegmentTree(int n) : n(n), root(new Node(0)) {}

    void update(int pos, int val) {
        root->update(0, n, pos, val);
    }

    int maximum(int l, int r) {
        return root->maximum(0, n, l, r);
    }

private:
    int n;
    Node* root = nullptr;
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        a[i] += n - i;
    }

    const int INF = 1'500'000'001;
    ImplicitSegmentTree left(INF);
    vector<int> l_ws, l_cnts;
    for (int i = 0; i < n; i++) {
        // delete i
        int l_w = 0;
        int l_cnt = 0;
        if (i) {
            l_w = a[i-1];
            l_cnt = 1 + left.maximum(0, l_w + 1);
            left.update(l_w, l_cnt);
        }
        l_ws.push_back(l_w);
        l_cnts.push_back(l_cnt);
    }

    int best = 0;

    ImplicitSegmentTree right(INF);
    for (int i = n-1; i >= 0; i--) {
        // delete i
        if (i == n-1) {
            best = max(best, l_cnts[i]);
        } else {
            int x = right.maximum(l_ws[i], INF);
            best = max(best, l_cnts[i] + x);
            right.update(a[i] - 1, x + 1);
        }
    }

    cout << n - (1 + best) << endl;
}


#include <bits/stdc++.h>
using namespace std;

class Node {
public:
    Node(int x) : x(x) {}

    void update(int l, int r, int pos, int val) {
        if (l + 1 == r) {
            x = val;
        } else {
            int m = (l + r) / 2;
            if (pos < m) {
                if (left == nullptr)
                    left = new Node(0);
                left->update(l, m, pos, val);
            } else {
                if (right == nullptr)
                    right = new Node(0);
                right->update(m, r, pos, val);
            }
            x = 0;
            if (left)
                x = std::max(x, left->x);
            if (right)
                x = std::max(x, right->x);
        }
    }

    int maximum(int l, int r, int rl, int rr) {
        if (rr <= l || rl >= r)
            return 0;
        if (rl <= l && r <= rr)
            return x;
        int m = (l + r) / 2;
        int res = 0;
        if (left)
            res = std::max(res, left->maximum(l, m, rl, rr));
        if (right)
            res = std::max(res, right->maximum(m, r, rl, rr));
        return res;
    }

    int x;
    Node* left = nullptr;
    Node* right = nullptr;
};

class ImplicitSegmentTree {
public:
    ImplicitSegmentTree(int n) : n(n), root(new Node(0)) {}

    void update(int pos, int val) {
        root->update(0, n, pos, val);
    }

    int maximum(int l, int r) {
        return root->maximum(0, n, l, r);
    }

private:
    int n;
    Node* root = nullptr;
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        a[i] += n - i;
    }

    const int INF = 1'500'000'001;
    ImplicitSegmentTree left(INF);
    vector<int> l_ws, l_cnts;
    for (int i = 0; i < n; i++) {
        // delete i
        int l_w = 0;
        int l_cnt = 0;
        if (i) {
            l_w = a[i-1];
            l_cnt = 1 + left.maximum(0, l_w + 1);
            left.update(l_w, l_cnt);
        }
        l_ws.push_back(l_w);
        l_cnts.push_back(l_cnt);
    }

    int best = 0;

    ImplicitSegmentTree right(INF);
    for (int i = n-1; i >= 0; i--) {
        // delete i
        if (i == n-1) {
            best = max(best, l_cnts[i]);
        } else {
            int x = right.maximum(l_ws[i], INF);
            best = max(best, l_cnts[i] + x);
        }
        right.update(a[i] - 1, right.maximum(a[i] - 1, INF) + 1);
    }

    cout << n - (1 + best) << endl;
}


#include <bits/stdc++.h>
using namespace std;

class Node {
public:
    Node(int x) : x(x) {}

    void update(int l, int r, int pos, int val) {
        if (l + 1 == r) {
            x = val;
        } else {
            int m = (l + r) / 2;
            if (pos < m) {
                if (left == nullptr)
                    left = new Node(0);
                left->update(l, m, pos, val);
            } else {
                if (right == nullptr)
                    right = new Node(0);
                right->update(m, r, pos, val);
            }
            x = 0;
            if (left)
                x = std::max(x, left->x);
            if (right)
                x = std::max(x, right->x);
        }
    }

    int maximum(int l, int r, int rl, int rr) {
        if (rr <= l || rl >= r)
            return 0;
        if (rl <= l && r <= rr)
            return x;
        int m = (l + r) / 2;
        int res = 0;
        if (left)
            res = std::max(res, left->maximum(l, m, rl, rr));
        if (right)
            res = std::max(res, right->maximum(m, r, rl, rr));
        return res;
    }

    int x;
    Node* left = nullptr;
    Node* right = nullptr;
};

class ImplicitSegmentTree {
public:
    ImplicitSegmentTree(int n) : n(n), root(new Node(0)) {}

    void update(int pos, int val) {
        root->update(0, n, pos, val);
    }

    int maximum(int l, int r) {
        return root->maximum(0, n, l, r);
    }

private:
    int n;
    Node* root = nullptr;
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        a[i] += n - i;
    }

    const int INF = 1'500'000'001;
    ImplicitSegmentTree left(INF);
    vector<int> l_ws, l_cnts;
    for (int i = 0; i < n; i++) {
        // delete i
        int l_w = 0;
        int l_cnt = 0;
        if (i) {
            l_w = a[i-1];
            l_cnt = 1 + left.maximum(0, l_w + 1);
            left.update(l_w, l_cnt);
        }
        l_ws.push_back(l_w);
        l_cnts.push_back(l_cnt);
    }

    int best = 0;

    ImplicitSegmentTree right(INF);
    for (int i = n-1; i >= 0; i--) {
        // delete i
        if (i == n-1) {
            best = max(best, l_cnts[i]);
        } else {
            int x = right.maximum(l_ws[i] - 1, INF);
            best = max(best, l_cnts[i] + x);
            right.update(a[i] - 1, x + 1);
        }
    }

    cout << n - (1 + best) << endl;
}


#include <bits/stdc++.h>
using namespace std;

class Node {
public:
    Node(int x) : x(x) {}

    void update(int l, int r, int pos, int val) {
        if (l + 1 == r) {
            x = val;
        } else {
            int m = (l + r) / 2;
            if (pos < m) {
                if (left == nullptr)
                    left = new Node(0);
                left->update(l, m, pos, val);
            } else {
                if (right == nullptr)
                    right = new Node(0);
                right->update(m, r, pos, val);
            }
            x = 0;
            if (left)
                x = std::max(x, left->x);
            if (right)
                x = std::max(x, right->x);
        }
    }

    int maximum(int l, int r, int rl, int rr) {
        if (rr <= l || rl >= r)
            return 0;
        if (rl <= l && r <= rr)
            return x;
        int m = (l + r) / 2;
        int res = 0;
        if (left)
            res = std::max(res, left->maximum(l, m, rl, rr));
        if (right)
            res = std::max(res, right->maximum(m, r, rl, rr));
        return res;
    }

    int x;
    Node* left = nullptr;
    Node* right = nullptr;
};

class ImplicitSegmentTree {
public:
    ImplicitSegmentTree(int n) : n(n), root(new Node(0)) {}

    void update(int pos, int val) {
        root->update(0, n, pos, val);
    }

    int maximum(int l, int r) {
        return root->maximum(0, n, l, r);
    }

private:
    int n;
    Node* root = nullptr;
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        a[i] += n - i;
    }

    const int INF = 1'500'000'001;
    ImplicitSegmentTree left(INF);
    vector<int> l_ws, l_cnts;
    for (int i = 0; i < n; i++) {
        // delete i
        int l_w = 0;
        int l_cnt = 0;
        if (i) {
            l_w = a[i-1];
            l_cnt = 1 + left.maximum(0, l_w + 1);
            left.update(l_w, l_cnt);
        }
        l_ws.push_back(l_w);
        l_cnts.push_back(l_cnt);
    }

    int best = 0;

    ImplicitSegmentTree right(INF);
    for (int i = n-1; i >= 0; i--) {
        // delete i
        if (i == n-1) {
            best = max(best, l_cnts[i]);
        } else {
            int x = right.maximum(l_ws[i] - 1, INF);
            best = max(best, l_cnts[i] + x);
            right.update(l_ws[i] - 1, x + 1);
        }
    }

    cout << n - (1 + best) << endl;
}


#include <bits/stdc++.h>
using namespace std;

class SegmentTree {
public:
    SegmentTree(int count) {
        n = count;
        data.assign(2 * n, 0);
    }

    void update(int idx, int value) {
        idx += n;
        data[idx] = value;

        while (idx > 1) {
            idx /= 2;
            data[idx] = std::max(data[2 * idx], data[2 * idx + 1]);
        }
    }

    int maximum(int left, int right) { // interval [left, right)
        int ret = 0;
        left += n;
        right += n;

        while (left < right) {
            if (left & 1) ret = std::max(ret, data[left++]);
            if (right & 1) ret = std::max(ret, data[--right]);
            left >>= 1;
            right >>= 1;
        }
        return ret;
    }

private:
    int n;
    std::vector<int> data;
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        a[i] += n - i;
    }

    auto v = a;
    sort(v.begin(), v.end());
    auto end = unique(v.begin(), v.end());

    const int INF = end - v.begin() + 1;
    SegmentTree left(INF);
    vector<int> l_ws, l_cnts;
    for (int i = 0; i < n; i++) {
        // delete i
        int l_w = 0;
        int l_cnt = 0;
        if (i) {
            l_w = lower_bound(v.begin(), end, a[i-1]) - v.begin();
            l_cnt = 1 + left.maximum(0, l_w + 1);
            left.update(l_w, l_cnt);
            l_w = a[i-1];
        }
        l_ws.push_back(l_w);
        l_cnts.push_back(l_cnt);
    }

    int best = 0;

    SegmentTree right(INF);
    for (int i = n-1; i >= 0; i--) {
        // delete i
        if (i == n-1) {
            best = max(best, l_cnts[i]);
        } else {
            int w = lower_bound(v.begin(), end, l_ws[i] - 1) - v.begin();
            int x = right.maximum(w, INF);
            best = max(best, l_cnts[i] + x);
        }
        int w = lower_bound(v.begin(), end, a[i]) - v.begin();
        right.update(w, right.maximum(w, INF) + 1);
    }

    cout << n - (1 + best) << endl;
}


#include <bits/stdc++.h>
using namespace std;

class Node {
public:
    Node(int x) : x(x) {}

    void update(int l, int r, int pos, int val) {
        if (l + 1 == r) {
            x = val;
        } else {
            int m = (l + r) / 2;
            if (pos < m) {
                if (left == nullptr)
                    left = new Node(0);
                left->update(l, m, pos, val);
            } else {
                if (right == nullptr)
                    right = new Node(0);
                right->update(m, r, pos, val);
            }
            x = 0;
            if (left)
                x = std::max(x, left->x);
            if (right)
                x = std::max(x, right->x);
        }
    }

    int maximum(int l, int r, int rl, int rr) {
        if (rr <= l || rl >= r)
            return 0;
        if (rl <= l && r <= rr)
            return x;
        int m = (l + r) / 2;
        int res = 0;
        if (left)
            res = std::max(res, left->maximum(l, m, rl, rr));
        if (right)
            res = std::max(res, right->maximum(m, r, rl, rr));
        return res;
    }

    int x;
    Node* left = nullptr;
    Node* right = nullptr;
};

class ImplicitSegmentTree {
public:
    ImplicitSegmentTree(int n) : n(n), root(new Node(0)) {}

    void update(int pos, int val) {
        root->update(0, n, pos, val);
    }

    int maximum(int l, int r) {
        return root->maximum(0, n, l, r);
    }

private:
    int n;
    Node* root = nullptr;
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        a[i] += n - i;
    }

    const int INF = 1'500'000'001;
    ImplicitSegmentTree left(INF);
    vector<int> l_ws, l_cnts;
    for (int i = 0; i < n; i++) {
        // delete i
        int l_w = 0;
        int l_cnt = 0;
        if (i) {
            l_w = a[i-1];
            l_cnt = 1 + left.maximum(0, l_w + 1);
            left.update(l_w, l_cnt);
        }
        l_ws.push_back(l_w);
        l_cnts.push_back(l_cnt);
    }

    int best = 0;

    ImplicitSegmentTree right(INF);
    for (int i = n-1; i >= 0; i--) {
        // delete i
        if (i == n-1) {
            best = max(best, l_cnts[i]);
        } else {
            int x = right.maximum(l_ws[i] - 1, INF);
            best = max(best, l_cnts[i] + x);
            right.update(a[i], x + 1);
        }
    }

    cout << n - (1 + best) << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define fr(i,j,k) for(int i=j;i<k;i++)
#define f(n) fr(i,0,n)
#define f1(n) fr(i,1,n+1)
#define pb push_back
#define F first
#define S second
#define all(x) x.begin(), x.end()
const int mod = 1e9 + 7;
const int maxn = 200005;
int n, a[maxn];
void go() {
    int n;
    cin >> n;
    f1(n) {
        cin >> a[i];
    }
    vector<int>v1,v2;
    f(n + 2) {
        v1.pb(mod);
        v2.pb(mod);
    }
    v1[0] = v2[0]=-mod;
    int ls = 0, ans = 0;
    f1(n) {
        int idx1 = upper_bound(all(v1),a[i]-i+1) - v1.begin();
        ans = max(ans, idx1);
        v1[idx1] = a[i] - i + 1;
        v1[ls] = min(v1[ls],v2[ls]);
        ans = max(ans, ls);
        ls = upper_bound(all(v2),a[i]-i) - v2.begin();
        v2[ls] = a[i] - i;
    }
    cout << max(0,n-ans -1) << '\n';
}
int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int c = 0;
    int t;
    if (!c) {
        t = 1;
    }
    else {
        cin >> t;
    }
    while (t--) {
        go();
    }

}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define fr(i,j,k) for(int i=j;i<k;i++)
#define f(n) fr(i,0,n)
#define f1(n) fr(i,1,n+1)
#define pb push_back
#define F first
#define S second
#define all(x) x.begin(), x.end()
const int mod = 1e9 + 7;
const int maxn = 200005;
int n, a[maxn];
void go() {
    int n;
    cin >> n;
    f1(n) {
        cin >> a[i];
    }
    vector<int>v1,v2;
    f(n + 2) {
        v1.pb(mod);
        v2.pb(mod);
    }
    v1[0] = v2[0]=-mod;
    int ls = 0, ans = 0;
    f1(n) {
        int idx1 = upper_bound(all(v1),a[i]-i+1) - v1.begin();
        ans = max(ans, idx1);
        v1[idx1] = a[i] - i + 1;
        v1[ls] = min(v1[ls],v2[ls]);
        ans = max(ans, ls);
        ls = upper_bound(all(v2),a[i]-i) - v2.begin();
        v2[ls] = a[i] - i;
    }
    cout << n-ans -1 << '\n';
}
int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int c = 0;
    int t;
    if (!c) {
        t = 1;
    }
    else {
        cin >> t;
    }
    while (t--) {
        go();
    }

}


#include<bits/stdc++.h>
using namespace std;

const int maxn = 2e5 + 100;

int a[maxn];

int tree[4*maxn];

void update(int node, int l, int r, int pos, int val)
{
    if(l > r || l > pos || r < pos)
        return;
    if( l == r && l == pos)
    {
        tree[node] = max(tree[node], val);
        return;
    }
    int mid = (l+r) >> 1;
    update(2*node, l , mid, pos, val);
    update(2*node+1, mid+1 , r, pos, val);
    tree[node] = max(tree[2*node], tree[2*node+1]);
}

int query(int node, int l, int r, int x, int y)
{
    if(l > r || l > y || r < x)
        return 0;
    if(x <= l && r <= y)
        return tree[node];
    int mid = (l+r) >> 1;
    int a = query(2*node,l,mid,x,y);
    int b = query(2*node+1,mid+1,r,x,y);
    return max(a,b);
}

map<int,int>mapa;

int pref[maxn];

int main()
{
    int n;
    scanf("%d",&n);
    // mapa[1] = 0;
    for(int i = 1; i <= n; i++)
    {
        scanf("%d",&a[i]);
        a[i] -= i;
        //cout << a[i] << ' ';
        mapa[a[i]] = 0;
    }

    //cout << endl;

    int idx = 1;
    for(auto &x : mapa)
    {
        x.second = idx++;
    }

    for(int i = 1 ; i <= n; i++)
    {
        int val = mapa[a[i]];
        //cout << i << ' ' << val << endl;
        pref[i] = query(1, 1, idx, 1, val) + 1;
        update(1, 1, idx, val, pref[i]);
        //cout << pref[i] << ' ';
    }
    //cout << endl;
    int ans = n - pref[n-1] - 1;
    memset(tree, 0, sizeof(tree));
    //cout << ans << endl;

    for(int i = n-1; i >= 1; i--)
    {
        int val = mapa[a[i+1]];
        int q = query(1, 1, idx, val, idx);
        update(1, 1, idx, val, q+1);
        //cout << q+1 << ' ';
        //cout << "i: " << i << " " << pref[i-1] << " -> " << query(1, 1, idx, mapa[a[i-1]], idx) << endl;
        int lds = 0;
        if(mapa.count(a[i-1]-1))
            lds = pref[i-1] + query(1, 1, idx, mapa[a[i-1]-1], idx);
        else
            lds = pref[i-1] + query(1, 1, idx, mapa[a[i-1]], idx);
        ans = min(ans, n - lds - 1);
    }
    //cout << endl;
    printf("%d\n",ans);

    return 0;
}


#include<bits/stdc++.h>
using namespace std;

const int maxn = 5e5 + 100;

int a[maxn];

int tree[4*maxn];

void update(int node, int l, int r, int pos, int val)
{
    if(l > r || l > pos || r < pos)
        return;
    if( l == r && l == pos)
    {
        tree[node] = max(tree[node], val);
        return;
    }
    int mid = (l+r) >> 1;
    update(2*node, l , mid, pos, val);
    update(2*node+1, mid+1 , r, pos, val);
    tree[node] = max(tree[2*node], tree[2*node+1]);
}

int query(int node, int l, int r, int x, int y)
{
    if(l > r || l > y || r < x)
        return -1;
    if(x <= l && r <= y)
        return tree[node];
    int mid = (l+r) >> 1;
    int a = query(2*node,l,mid,x,y);
    int b = query(2*node+1,mid+1,r,x,y);
    return max(a,b);
}

map<int,int>mapa;

int pref[maxn];

int main()
{
    int n;
    scanf("%d",&n);

    for(int i = 1; i <= n; i++)
    {
        scanf("%d",&a[i]);
        a[i] -= i;
        mapa[a[i]] = 0;
        mapa[a[i]-1] = 0;
    }

    int idx = 1;
    for(auto &x : mapa)
    {
        x.second = idx++;
    }

    for(int i = 1 ; i <= n; i++)
    {
        int val = mapa[a[i]];
        pref[i] = query(1, 1, idx, 1, val) + 1;
        update(1, 1, idx, val, pref[i]);
    }

    int ans = n - query(1, 1, idx, 1, idx) - 1;
    memset(tree, 0, sizeof(tree));
    for(int i = n-1; i > 1 ; i--)
    {
        int val = mapa[a[i+1]];
        int q = query(1, 1, idx, val, idx);
        update(1, 1, idx, val, q+1);
        int lds = pref[i-1] + query(1, 1, idx, mapa[a[i-1]-1], idx);
        ans = min(ans, n - lds - 1);
    }

    printf("%d\n",ans);

    return 0;
}


#include<bits/stdc++.h>
using namespace std;

const int maxn = 2e5 + 100;

int a[maxn];

int tree[4*maxn];

void update(int node, int l, int r, int pos, int val)
{
    if(l > r || l > pos || r < pos)
        return;
    if( l == r && l == pos)
    {
        tree[node] = max(tree[node], val);
        return;
    }
    int mid = (l+r) >> 1;
    update(2*node, l , mid, pos, val);
    update(2*node+1, mid+1 , r, pos, val);
    tree[node] = max(tree[2*node], tree[2*node+1]);
}

int query(int node, int l, int r, int x, int y)
{
    if(l > r || l > y || r < x)
        return 0;
    if(x <= l && r <= y)
        return tree[node];
    int mid = (l+r) >> 1;
    int a = query(2*node,l,mid,x,y);
    int b = query(2*node+1,mid+1,r,x,y);
    return max(a,b);
}

map<int,int>mapa;

int pref[maxn];

int main()
{
    int n;
    scanf("%d",&n);
    for(int i = 0; i < n; i++)
    {
        scanf("%d",&a[i]);
        a[i] -= i;
        mapa[a[i]] = 0;
    }

    int idx = 1;
    for(auto &x : mapa)
    {
        x.second = idx++;
    }

    for(int i = 0 ; i < n; i++)
    {
        int val = mapa[a[i]];
        int q = query(1, 1, idx, 1, val);
        update(1, 1, idx, val, q+1);
        pref[i] = q+1;
    }
    int ans = n - query(1, 1 , idx, 1, idx) - 1;
    memset(tree, 0, sizeof(tree));
    //cout << ans << endl;
    for(int i = n-1; i >= 1; i--)
    {
        int val = mapa[a[i+1]];
        int q = query(1, 1, idx, val, idx);
        update(1, 1, idx, val, q+1);
        int lds = pref[i-1] + query(1, 1, idx, mapa[a[i-1]], idx);
        ans = min(ans, n - lds - 1);
    }
    printf("%d\n",ans);

    return 0;
}


#include<bits/stdc++.h>
using namespace std;

const int maxn = 2e5 + 100;

int a[maxn];

int tree[4*maxn];

void update(int node, int l, int r, int pos, int val)
{
    if(l > r || l > pos || r < pos)
        return;
    if( l == r && l == pos)
    {
        tree[node] = max(tree[node], val);
        return;
    }
    int mid = (l+r) >> 1;
    update(2*node, l , mid, pos, val);
    update(2*node+1, mid+1 , r, pos, val);
    tree[node] = max(tree[2*node], tree[2*node+1]);
}

int query(int node, int l, int r, int x, int y)
{
    if(l > r || l > y || r < x)
        return -1;
    if(x <= l && r <= y)
        return tree[node];
    int mid = (l+r) >> 1;
    int a = query(2*node,l,mid,x,y);
    int b = query(2*node+1,mid+1,r,x,y);
    return max(a,b);
}

map<int,int>mapa;

int pref[maxn];

int main()
{
    int n;
    scanf("%d",&n);

    for(int i = 1; i <= n; i++)
    {
        scanf("%d",&a[i]);
        a[i] -= i;
        mapa[a[i]] = 0;
        mapa[a[i]-1] = 0;
    }

    int idx = 1;
    for(auto &x : mapa)
    {
        x.second = idx++;
    }

    for(int i = 1 ; i <= n; i++)
    {
        int val = mapa[a[i]];
        pref[i] = query(1, 1, idx, 1, val) + 1;
        update(1, 1, idx, val, pref[i]);
    }

    int ans = n - query(1, 1, idx, 1, idx) - 1;
    memset(tree, 0, sizeof(tree));
    for(int i = n-1; i > 1 ; i--)
    {
        int val = mapa[a[i+1]];
        int q = query(1, 1, idx, val, idx);
        update(1, 1, idx, val, q+1);
        int lds = pref[i-1] + query(1, 1, idx, mapa[a[i-1]-1], idx);
        ans = min(ans, n - lds - 1);
    }

    printf("%d\n",ans);

    return 0;
}


#include<bits/stdc++.h>
using namespace std;

const int maxn = 5e5 + 100;

int a[maxn];

int tree[4*maxn];

void update(int node, int l, int r, int pos, int val)
{
    if(l > r || l > pos || r < pos)
        return;
    if( l == r && l == pos)
    {
        tree[node] = max(tree[node], val);
        return;
    }
    int mid = (l+r) >> 1;
    update(2*node, l , mid, pos, val);
    update(2*node+1, mid+1 , r, pos, val);
    tree[node] = max(tree[2*node], tree[2*node+1]);
}

int query(int node, int l, int r, int x, int y)
{
    if(l > r || l > y || r < x)
        return -1;
    if(x <= l && r <= y)
        return tree[node];
    int mid = (l+r) >> 1;
    int a = query(2*node,l,mid,x,y);
    int b = query(2*node+1,mid+1,r,x,y);
    return max(a,b);
}

map<int,int>mapa;

int pref[maxn];

int main()
{
    int n;
    scanf("%d",&n);

    for(int i = 1; i <= n; i++)
    {
        scanf("%d",&a[i]);
        a[i] -= i;
        mapa[a[i]] = 0;
        mapa[a[i]-1] = 0;
    }

    int idx = 1;
    for(auto &x : mapa)
    {
        x.second = idx++;
    }

    for(int i = 1 ; i <= n; i++)
    {
        int val = mapa[a[i]];
        pref[i] = query(1, 1, idx, 1, val) + 1;
        update(1, 1, idx, val, pref[i]);
    }

    int ans = n - query(1, 1, idx, 1, idx) - 1;
    memset(tree, 0, sizeof(tree));
    for(int i = n-1; i > 1 ; i--)
    {
        int val = mapa[a[i+1]];
        int q = query(1, 1, idx, val, idx);
        update(1, 1, idx, val, q+1);
        int lds = pref[i-1] + query(1, 1, idx, mapa[a[i-1]-1], idx);
        ans = min(ans, n - lds - 1);
    }

    printf("%d\n",max(0,ans));

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int maxn = 2e6+100;

int dp[maxn][2],a[maxn],b[maxn];

struct BIT{
    #define lowbit(i) (i&-i)
    int S[maxn]={},n=0;
    void init(int x){
        this->n=x;
        for(int i=0;i<=n;i++)S[i]=0;
    }
    void del(int x){
        for(int i=x;i<=n;i+=lowbit(i))S[i]=0;
    }
    void add(int x,int v){
        for(int i=x;i<=n;i+=lowbit(i))
            S[i]=max(S[i],v);
        return ;
    }
    int ask(int x){
        if(x==0)return 0;
        int res=0;
        for(int i=x;i>=1;i-=lowbit(i))
            res=max(res,S[i]);
        return res;
    }
}bit[3];

int main(){
    int n;cin>>n;
    vector<int>G;
    for(int i=1;i<=n;i++)scanf("%d",a+i),b[i]=a[i]-i+1,a[i]=a[i]-i;
    for(int i=1;i<=n;i++){
        G.push_back(a[i]);
        G.push_back(b[i]);
    }
    sort(G.begin(),G.end());
    G.erase(unique(G.begin(),G.end()),G.end());
    for(int i=0;i<3;i++)bit[i].init(G.size());
    for(int i=1;i<=n;i++){
        a[i]=lower_bound(G.begin(),G.end(),a[i])-G.begin()+1;
        b[i]=lower_bound(G.begin(),G.end(),b[i])-G.begin()+1;
      //  cout<<a[i]<<" "<<b[i]<<endl;
    }
    puts("*");
    int ans=n;
    for(int i=1;i<=n;i++){
        dp[i][0]=bit[0].ask(a[i])+1;
      //  cout<<bit[0].ask(a[i])<<endl;
        if(i>1)dp[i][1]=bit[1].ask(b[i])+1;
        if(i>2)dp[i][1]=max(dp[i][1],bit[2].ask(b[i])+1);
        bit[0].add(a[i],dp[i][0]);
        bit[1].add(b[i],dp[i][1]);
        if(i>1)bit[2].add(a[i-1],dp[i-1][0]);
     //   cout<<dp[i][0]<<" "<<dp[i][1]<<endl;
        ans=min(ans,n-1-dp[i][0]);
        ans=min(ans,n-1-dp[i][1]);
    }
    cout<<max(ans,0)<<endl;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int maxn = 2e6+100;

int dp[maxn][2],a[maxn],b[maxn];

struct BIT{
    #define lowbit(i) (i&-i)
    int S[maxn]={},n=0;
    void init(int x){
        this->n=x;
        for(int i=0;i<=n;i++)S[i]=0;
    }
    void del(int x){
        for(int i=x;i<=n;i+=lowbit(i))S[i]=0;
    }
    void add(int x,int v){
        for(int i=x;i<=n;i+=lowbit(i))
            S[i]=max(S[i],v);
        return ;
    }
    int ask(int x){
        if(x==0)return 0;
        int res=0;
        for(int i=x;i>=1;i-=lowbit(i))
            res=max(res,S[i]);
        return res;
    }
}bit[3];

int main(){
    int n;cin>>n;
    vector<int>G;
    for(int i=1;i<=n;i++)scanf("%d",a+i),b[i]=a[i]-i+1,a[i]=a[i]-i;
    for(int i=1;i<=n;i++){
        G.push_back(a[i]);
        G.push_back(b[i]);
    }
    sort(G.begin(),G.end());
    G.erase(unique(G.begin(),G.end()),G.end());
    for(int i=0;i<3;i++)bit[i].init(G.size());
    for(int i=1;i<=n;i++){
        a[i]=lower_bound(G.begin(),G.end(),a[i])-G.begin()+1;
        b[i]=lower_bound(G.begin(),G.end(),b[i])-G.begin()+1;
    //    cout<<a[i]<<" "<<b[i]<<endl;
    }
    int ans=n;
    for(int i=1;i<=n;i++){
        dp[i][0]=bit[0].ask(a[i])+1;
      //  cout<<bit[0].ask(a[i])<<endl;
        dp[i][1]=max(bit[1].ask(b[i]),bit[2].ask(b[i]))+1;
        bit[0].add(a[i],dp[i][0]);
        bit[1].add(b[i],dp[i][1]);
        if(i>1)bit[2].add(a[i-1],dp[i-1][0]);
        ans=min(ans,n-dp[i][0]);
        ans=min(ans,n-1-dp[i][1]);
    }
    cout<<ans<<endl;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int maxn = 2e6+100;

int dp[maxn][2],a[maxn],b[maxn];

struct BIT{
    #define lowbit(i) (i&-i)
    int S[maxn]={},n=0;
    void init(int x){
        this->n=x;
        for(int i=0;i<=n;i++)S[i]=0;
    }
    void del(int x){
        for(int i=x;i<=n;i+=lowbit(i))S[i]=0;
    }
    void add(int x,int v){
        for(int i=x;i<=n;i+=lowbit(i))
            S[i]=max(S[i],v);
        return ;
    }
    int ask(int x){
        if(x==0)return 0;
        int res=0;
        for(int i=x;i>=1;i-=lowbit(i))
            res=max(res,S[i]);
        return res;
    }
}bit[3];

int main(){
    int n;cin>>n;
    vector<int>G;
    for(int i=1;i<=n;i++)scanf("%d",a+i),b[i]=a[i]-i+1,a[i]=a[i]-i;
    for(int i=1;i<=n;i++){
        G.push_back(a[i]);
        G.push_back(b[i]);
    }
    sort(G.begin(),G.end());
    G.erase(unique(G.begin(),G.end()),G.end());
    for(int i=0;i<3;i++)bit[i].init(G.size());
    for(int i=1;i<=n;i++){
        a[i]=lower_bound(G.begin(),G.end(),a[i])-G.begin()+1;
        b[i]=lower_bound(G.begin(),G.end(),b[i])-G.begin()+1;
      //  cout<<a[i]<<" "<<b[i]<<endl;
    }
   // puts("*");
    int ans=n;
    for(int i=1;i<=n;i++){
        dp[i][0]=bit[0].ask(a[i])+1;
      //  cout<<bit[0].ask(a[i])<<endl;
        if(i>1)dp[i][1]=bit[1].ask(b[i])+1;
        if(i>2)dp[i][1]=max(dp[i][1],bit[2].ask(b[i])+1);
        bit[0].add(a[i],dp[i][0]);
        bit[1].add(b[i],dp[i][1]);
        if(i>1)bit[2].add(a[i-1],dp[i-1][0]);
     //   cout<<dp[i][0]<<" "<<dp[i][1]<<endl;
        ans=min(ans,n-1-dp[i][0]);
        ans=min(ans,n-1-dp[i][1]);
    }
    cout<<max(ans,0)<<endl;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 200010,inf = 0x7fffffff;
int n,a[maxn],b[maxn],cnt,ans = inf,f[maxn],g[maxn],c1[maxn],c2[maxn];

void add1(int x,int v)
{
    while (x <= cnt)
    {
        c1[x] = max(c1[x],v);
        x += x & (-x);
    }
}

void add2(int x,int v)
{
    while (x <= cnt)
    {
        c2[x] = max(c2[x],v);
        x += x & (-x);
    }
}

int query1(int x)
{
    int res = 0;
    while (x)
    {
        res = max(res,c1[x]);
        x -= x & (-x);
    }
    return res;
}

int query2(int x)
{
    int res = 0;
    while (x)
    {
        res = max(res,c2[x]);
        x -= x & (-x);
    }
    return res;
}

int find(int x)
{
    int l = 1,r = cnt,res = 0;
    while (l <= r)
    {
        int mid = (l + r) >> 1;
        if (b[mid] <= x)
        {
            res = mid;
            l = mid + 1;
        }
        else
            r = mid - 1;
    }
    return res;
}

int main()
{
    scanf("%d",&n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d",&a[i]);
        b[i] = a[i] - i;
    }
    sort(b + 1,b + 1 + n);
    cnt = unique(b + 1,b + 1 + n) - b - 1;
    for (int i = 1; i <= n; i++)
    {
        int t = find(a[i] - i);
        f[i] = query1(t) + 1;
        g[i] = max(g[i],1);
        if (i < n)
            g[i + 1] = query1(find(a[i + 1] - i)) + 1;
        add1(t,f[i]);
        if (i > 1)
        {
            g[i] = max(g[i],query2(t) + 1);
            add2(t,g[i]);
        }
    }
    ans = n;
    for (int i = 1; i <= n; i++)
    {
        ans = min(ans,n - 1 - f[i]);
        if (i > 1)
            ans = min(ans,n - 1 - g[i]);
    }
    ans = max(ans,0);
    printf("%d\n",ans);

    return 0;
}


// FUCKED UP FUCKED UP FUCKED UP FUCKED UP FUCKED UP
#include <bits/stdc++.h>
using namespace std;

#pragma GCC optimize("O2,no-stack-protector,unroll-loops,fast-math")

#define F first
#define S second
#define pb push_back
#define SZ(x) (ll)(x.size())
#define all(x) x.begin(),x.end()
#define MP make_pair

typedef int ll;
typedef long double ld;
typedef pair<ll,ll> pll;

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const ll maxn=2e5+10, maxm=1e6+10, lg=10, mod=1e9+7, inf=1e18;

ll n,mx,dp1[maxn],dp2[maxn];

int main(){
	ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);

	memset(dp1,69,sizeof(dp1)), memset(dp2,69,sizeof(dp2));
	cin>>n;
	dp1[0]=-mod;
	for(int i=0,x,nw=0;i<n;i++){
		cin>>x;
		ll lb=lower_bound(dp2,dp2+maxn,x-i)-dp2;
		dp2[lb]=x-i, dp2[nw]=min(dp2[nw],dp1[nw]);
		mx=max({mx,lb,nw});
		nw=upper_bound(dp1,dp1+maxn,x-i-1)-dp1;
		dp1[nw]=x-i-1;
	}
	cout<<n-1-mx;

	return 0;
}

// a denial a denial a denial a denial a denial a denial


// FUCKED UP FUCKED UP FUCKED UP FUCKED UP FUCKED UP
#include <bits/stdc++.h>
using namespace std;

#pragma GCC optimize("O2,no-stack-protector,unroll-loops,fast-math")

#define F first
#define S second
#define pb push_back
#define SZ(x) (ll)(x.size())
#define all(x) x.begin(),x.end()
#define MP make_pair

typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pll;

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const ll maxn=2e5+10, maxm=1e6+10, lg=10, mod=1e9+7, inf=1e18;

ll n,mx,dp1[maxn],dp2[maxn];

int main(){
	ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);

	memset(dp1,69,sizeof(dp1)), memset(dp2,69,sizeof(dp2));
	cin>>n;
	dp1[0]=-inf;
	for(int i=0,x,nw=0;i<n;i++){
		cin>>x;
		ll lb=lower_bound(dp2,dp2+maxn,x-i)-dp2;
		dp2[lb]=x-i, dp2[nw]=min(dp2[nw],dp1[nw]);
		mx=max({mx,lb,nw});
		nw=upper_bound(dp1,dp1+maxn,x-i-1)-dp1;
		dp1[nw]=x-i-1;
	}
	cout<<n-1-mx;

	return 0;
}

// a denial a denial a denial a denial a denial a denial


// FUCKED UP FUCKED UP FUCKED UP FUCKED UP FUCKED UP
#include <bits/stdc++.h>
using namespace std;

#pragma GCC optimize("O2,no-stack-protector,unroll-loops,fast-math")

#define F first
#define S second
#define pb push_back
#define SZ(x) (ll)(x.size())
#define all(x) x.begin(),x.end()
#define MP make_pair

typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pll;

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const ll maxn=2e5+10, maxm=1e6+10, lg=10, mod=1e9+7, inf=1e18;

ll n,mx,dp1[maxn],dp2[maxn];

int main(){
	ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);

	memset(dp1,69,sizeof(dp1)), memset(dp2,69,sizeof(dp2)); dp1[0]=-inf;
	cin>>n;
	for(ll i=0,x,nw=0;i<n;i++){
		cin>>x;
		ll ub=upper_bound(dp2,dp2+maxn,x-i)-dp2;
		dp2[ub]=x-i; dp2[nw]=min(dp2[nw],dp1[nw]);
		mx=max({mx,ub,nw});
		nw=upper_bound(dp1,dp1+maxn,x-i-1)-dp1;
		dp1[nw]=x-i-1;
	}
	cout<<n-1-mx;

	return 0;
}
// a denial a denial a denial a denial a denial a denial


// FUCKED UP FUCKED UP FUCKED UP FUCKED UP FUCKED UP
#include <bits/stdc++.h>
using namespace std;

#pragma GCC optimize("O2,no-stack-protector,unroll-loops,fast-math")

#define F first
#define S second
#define pb push_back
#define SZ(x) (ll)(x.size())
#define all(x) x.begin(),x.end()
#define MP make_pair

typedef int ll;
typedef long double ld;
typedef pair<ll,ll> pll;

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const ll maxn=2e5+10, maxm=1e6+10, lg=10, mod=1e9+7, inf=1e18;

ll n,mx,dp1[maxn],dp2[maxn];

int main(){
	ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);

	memset(dp1,69,sizeof(dp1)), memset(dp2,69,sizeof(dp2));
	cin>>n;
	dp1[0]=-inf;
	for(int i=0,x,nw=0;i<n;i++){
		cin>>x;
		ll lb=lower_bound(dp2,dp2+maxn,x-i)-dp2;
		dp2[lb]=x-i, dp2[nw]=min(dp2[nw],dp1[nw]);
		mx=max({mx,lb,nw});
		nw=upper_bound(dp1,dp1+maxn,x-i-1)-dp1;
		dp1[nw]=x-i-1;
	}
	cout<<n-1-mx;

	return 0;
}

// a denial a denial a denial a denial a denial a denial


// FUCKED UP FUCKED UP FUCKED UP FUCKED UP FUCKED UP
#include <bits/stdc++.h>
using namespace std;

#pragma GCC optimize("O2,no-stack-protector,unroll-loops,fast-math")

#define F first
#define S second
#define pb push_back
#define SZ(x) (ll)(x.size())
#define all(x) x.begin(),x.end()
#define MP make_pair

typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pll;

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const ll maxn=2e5+10, maxm=1e6+10, lg=10, mod=1e9+7, inf=1e18;

ll n,mx,dp1[maxn],dp2[maxn];

int main(){
	ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);

	memset(dp1,69,sizeof(dp1)), memset(dp2,69,sizeof(dp2));
	cin>>n;
	dp1[0]=-inf;
	for(ll i=0,x,nw=0;i<n;i++){
		cin>>x;
		ll lb=lower_bound(dp2,dp2+maxn,x-i)-dp2;
		dp2[lb]=x-i, dp2[nw]=min(dp2[nw],dp1[nw]);
		mx=max({mx,lb,nw});
		nw=upper_bound(dp1,dp1+maxn,x-i-1)-dp1;
		dp1[nw]=x-i-1;
	}
	cout<<n-1-mx;

	return 0;
}

// a denial a denial a denial a denial a denial a denial


// >>> TEMPLATES
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using i32 = int32_t;
using i64 = int64_t;
using u32 = uint32_t;
using u64 = uint64_t;
#define int ll
#define double ld
#define rep(i,n) for (int i = 0; i < (int)(n); i++)
#define rep1(i,n) for (int i = 1; i <= (int)(n); i++)
#define repR(i,n) for (int i = (int)(n)-1; i >= 0; i--)
#define rep1R(i,n) for (int i = (int)(n); i >= 1; i--)
#define loop(i,a,B) for (int i = a; i B; i++)
#define loopR(i,a,B) for (int i = a; i B; i--)
#define all(x) (x).begin(), (x).end()
#define allR(x) (x).rbegin(), (x).rend()
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define fst first
#define snd second
template <class Int> auto constexpr inf = numeric_limits<Int>::max()/2-1;
auto constexpr INF32 = inf<int32_t>;
auto constexpr INF64 = inf<int64_t>;
auto constexpr INF   = inf<int>;
#ifdef LOCAL
#include "debug.hpp"
#else
#define dump(...) (void)(0)
#define say(x) (void)(0)
#define debug if (0)
#endif
template <class T> using pque_max = priority_queue<T>;
template <class T> using pque_min = priority_queue<T, vector<T>, greater<T> >;
template <class T, class = typename T::iterator, class = typename enable_if<!is_same<T, string>::value>::type>
ostream& operator<<(ostream& os, T const& v) { bool f = true; for (auto const& x : v) os << (f ? "" : " ") << x, f = false; return os; }
template <class T, class = typename T::iterator, class = typename enable_if<!is_same<T, string>::value>::type>
istream& operator>>(istream& is, T &v) { for (auto& x : v) is >> x; return is; }
template <class T, class S> ostream& operator<<(ostream& os, pair<T,S> const& p) { return os << "(" << p.first << ", " << p.second << ")"; }
template <class T, class S> istream& operator>>(istream& is, pair<T,S>& p) { return is >> p.first >> p.second; }
struct IOSetup { IOSetup() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(15); } } iosetup;
template <class F> struct FixPoint : private F {
    constexpr FixPoint(F&& f) : F(forward<F>(f)) {}
    template <class... T> constexpr auto operator()(T&&... x) const { return F::operator()(*this, forward<T>(x)...); }
};
struct MakeFixPoint {
    template <class F> constexpr auto operator|(F&& f) const { return FixPoint<F>(forward<F>(f)); }
};
#define MFP MakeFixPoint()|
#define def(name, ...) auto name = MFP [&](auto &&name, __VA_ARGS__)
template <class T, size_t d> struct vec_impl {
    using type = vector<typename vec_impl<T,d-1>::type>;
    template <class... U> static type make_v(size_t n, U&&... x) { return type(n, vec_impl<T,d-1>::make_v(forward<U>(x)...)); }
};
template <class T> struct vec_impl<T,0> { using type = T; static type make_v(T const& x = {}) { return x; } };
template <class T, size_t d = 1> using vec = typename vec_impl<T,d>::type;
template <class T, size_t d = 1, class... Args> auto make_v(Args&&... args) { return vec_impl<T,d>::make_v(forward<Args>(args)...); }
template <class T> void quit(T const& x) { cout << x << endl; exit(0); }
template <class T, class U> constexpr bool chmin(T& x, U const& y) { if (x > y) { x = y; return true; } return false; }
template <class T, class U> constexpr bool chmax(T& x, U const& y) { if (x < y) { x = y; return true; } return false; }
template <class It> constexpr auto sumof(It b, It e) { return accumulate(b,e,typename iterator_traits<It>::value_type{}); }
template <class T> int sz(T const& x) { return x.size(); }
template <class C, class T> int lbd(C const& v, T const& x) {
    return lower_bound(v.begin(), v.end(), x)-v.begin();
}
template <class C, class T> int ubd(C const& v, T const& x) {
    return upper_bound(v.begin(), v.end(), x)-v.begin();
}
const int dx[] = { 1,0,-1,0 };
const int dy[] = { 0,1,0,-1 };
constexpr int popcnt(ll x) { return __builtin_popcountll(x); }
template <class Int> struct Random {
    mt19937_64 mt{random_device{}()};
    //mt19937_64 mt{(unsigned)time(0)};
    Int a,b; // [a,b]
    Random(Int a, Int b) : a(a), b(b) {}
    Int operator()() { return uniform_int_distribution<Int>(a,b)(mt); }
};
template <class Int> Int rand(Int a, Int b) { // [a,b]
    static mt19937_64 mt{random_device{}()};
    return uniform_int_distribution<Int>(a,b)(mt);
}
// <<<
// >>> segment tree
template <class Handler>
struct Segtree : Handler {
    using Value = typename Handler::Value;
    using Handler::unit; // () -> Value
    using Handler::merge; // (Value,Value) -> Value

    vector<Value> v; // use v[1..2*cap-1]
    int cap; // // capacity: power of 2
    int n; // original size

    Segtree() {}
    template <class... T> Segtree(T&&... x) { init(forward<T>(x)...); }

    template <class F, class = decltype(declval<F>()(0))>
    void init(int n, F gen)  {
        assert(n >= 0); this->n = n;
        cap = n; //for (cap = 1; cap < n; cap <<= 1) ;;
        v.resize(2*cap, unit());
        for (int i = 0; i < n; i++) v[cap+i] = gen(i);
        for (int i = cap-1; i >= 1; i--) v[i] = merge(v[2*i],v[2*i+1]);
    }
    void init(int n) { init(n, [&](int) { return unit(); }); }
    void init(int n, Value const& x) { init(n, [&](int) { return x; }); }
    void init(vector<Value> const& v) { init(v.size(), [&](int i) { return v[i]; }); }
    int size() const { return n; }

    void set(int i, Value const& x) {
        assert(0 <= i); assert(i < size());
        i += cap; v[i] = x;
        while (i > 1) i >>= 1, v[i] = merge(v[2*i],v[2*i+1]);
    }
    Value operator[](int i) const { return get(i); }
    Value get(int i) const {
        assert(0 <= i); assert(i < size());
        return v[cap + i];
    }
    // [l,r)
    Value get(int l, int r) const {
        assert(0 <= l); assert(l <= r); assert(r <= size());
        Value x = unit(), y = unit();
        for (l += cap, r += cap; l < r; l >>= 1, r >>= 1) {
            if (l&1) x = merge(x, v[l++]);
            if (r&1) y = merge(v[--r], y);
        }
        return merge(x,y);
    }
    vector<Value> dat() const {
        vector<Value> ret(size());
        for (int i = 0; i < size(); i++) ret[i] = get(i);
        return ret;
    }
};
// <<<
struct RangeMax {
    using Value = int;
    constexpr static Value unit() { return -INF; }
    constexpr static Value merge(Value x, Value y) { return max(x,y); }
};

int32_t main() {
    int n; cin >> n;
    vector<int> a(n); cin >> a;
    rep (i,n) a[i] -= i;

    auto calc = [&]() {
        vector<int> idx(n);
        iota(all(idx),0);
        sort(all(idx), [&](int i, int j) { return mp(a[i],i) < mp(a[j],j); });

        vector<int> b(n);
        Segtree<RangeMax> seg(n);
        for (int i : idx) {
            b[i] = max(0LL,seg.get(0,i)) + 1;
            seg.set(i,b[i]);
        }
        return b;
    };

    vector<int> b[2];
    rep (i,2) {
        b[i] = calc();
        for (int &x : a) x = -x;
        reverse(all(a));
    }
    reverse(all(b[1]));
    dump(b[0]);
    dump(b[1]);

    int ans = INF;
    chmin(ans, n-*max_element(all(b[0])));
    chmin(ans, n-1-*max_element(b[0].begin(), b[0].end() - 1));
    chmin(ans, n-1-*max_element(b[1].begin() + 1, b[1].end()));

    map<int,int> m;
    rep (i,n-1) {
        if (m.count(a[i+1]+1)) {
            chmin(ans, n-1-(m[a[i+1]+1] + b[1][i+1]));
        }
        chmax(m[a[i]], b[0][i]);
    }

    cout << ans << endl;

}


// >>> TEMPLATES
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using i32 = int32_t;
using i64 = int64_t;
using u32 = uint32_t;
using u64 = uint64_t;
#define int ll
#define double ld
#define rep(i,n) for (int i = 0; i < (int)(n); i++)
#define rep1(i,n) for (int i = 1; i <= (int)(n); i++)
#define repR(i,n) for (int i = (int)(n)-1; i >= 0; i--)
#define rep1R(i,n) for (int i = (int)(n); i >= 1; i--)
#define loop(i,a,B) for (int i = a; i B; i++)
#define loopR(i,a,B) for (int i = a; i B; i--)
#define all(x) (x).begin(), (x).end()
#define allR(x) (x).rbegin(), (x).rend()
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define fst first
#define snd second
template <class Int> auto constexpr inf = numeric_limits<Int>::max()/2-1;
auto constexpr INF32 = inf<int32_t>;
auto constexpr INF64 = inf<int64_t>;
auto constexpr INF   = inf<int>;
#ifdef LOCAL
#include "debug.hpp"
#else
#define dump(...) (void)(0)
#define say(x) (void)(0)
#define debug if (0)
#endif
template <class T> using pque_max = priority_queue<T>;
template <class T> using pque_min = priority_queue<T, vector<T>, greater<T> >;
template <class T, class = typename T::iterator, class = typename enable_if<!is_same<T, string>::value>::type>
ostream& operator<<(ostream& os, T const& v) { bool f = true; for (auto const& x : v) os << (f ? "" : " ") << x, f = false; return os; }
template <class T, class = typename T::iterator, class = typename enable_if<!is_same<T, string>::value>::type>
istream& operator>>(istream& is, T &v) { for (auto& x : v) is >> x; return is; }
template <class T, class S> ostream& operator<<(ostream& os, pair<T,S> const& p) { return os << "(" << p.first << ", " << p.second << ")"; }
template <class T, class S> istream& operator>>(istream& is, pair<T,S>& p) { return is >> p.first >> p.second; }
struct IOSetup { IOSetup() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(15); } } iosetup;
template <class F> struct FixPoint : private F {
    constexpr FixPoint(F&& f) : F(forward<F>(f)) {}
    template <class... T> constexpr auto operator()(T&&... x) const { return F::operator()(*this, forward<T>(x)...); }
};
struct MakeFixPoint {
    template <class F> constexpr auto operator|(F&& f) const { return FixPoint<F>(forward<F>(f)); }
};
#define MFP MakeFixPoint()|
#define def(name, ...) auto name = MFP [&](auto &&name, __VA_ARGS__)
template <class T, size_t d> struct vec_impl {
    using type = vector<typename vec_impl<T,d-1>::type>;
    template <class... U> static type make_v(size_t n, U&&... x) { return type(n, vec_impl<T,d-1>::make_v(forward<U>(x)...)); }
};
template <class T> struct vec_impl<T,0> { using type = T; static type make_v(T const& x = {}) { return x; } };
template <class T, size_t d = 1> using vec = typename vec_impl<T,d>::type;
template <class T, size_t d = 1, class... Args> auto make_v(Args&&... args) { return vec_impl<T,d>::make_v(forward<Args>(args)...); }
template <class T> void quit(T const& x) { cout << x << endl; exit(0); }
template <class T, class U> constexpr bool chmin(T& x, U const& y) { if (x > y) { x = y; return true; } return false; }
template <class T, class U> constexpr bool chmax(T& x, U const& y) { if (x < y) { x = y; return true; } return false; }
template <class It> constexpr auto sumof(It b, It e) { return accumulate(b,e,typename iterator_traits<It>::value_type{}); }
template <class T> int sz(T const& x) { return x.size(); }
template <class C, class T> int lbd(C const& v, T const& x) {
    return lower_bound(v.begin(), v.end(), x)-v.begin();
}
template <class C, class T> int ubd(C const& v, T const& x) {
    return upper_bound(v.begin(), v.end(), x)-v.begin();
}
const int dx[] = { 1,0,-1,0 };
const int dy[] = { 0,1,0,-1 };
constexpr int popcnt(ll x) { return __builtin_popcountll(x); }
template <class Int> struct Random {
    mt19937_64 mt{random_device{}()};
    //mt19937_64 mt{(unsigned)time(0)};
    Int a,b; // [a,b]
    Random(Int a, Int b) : a(a), b(b) {}
    Int operator()() { return uniform_int_distribution<Int>(a,b)(mt); }
};
template <class Int> Int rand(Int a, Int b) { // [a,b]
    static mt19937_64 mt{random_device{}()};
    return uniform_int_distribution<Int>(a,b)(mt);
}
// <<<
// >>> segment tree
template <class Handler>
struct Segtree : Handler {
    using Value = typename Handler::Value;
    using Handler::unit; // () -> Value
    using Handler::merge; // (Value,Value) -> Value

    vector<Value> v; // use v[1..2*cap-1]
    int cap; // // capacity: power of 2
    int n; // original size

    Segtree() {}
    template <class... T> Segtree(T&&... x) { init(forward<T>(x)...); }

    template <class F, class = decltype(declval<F>()(0))>
    void init(int n, F gen)  {
        assert(n >= 0); this->n = n;
        cap = n; //for (cap = 1; cap < n; cap <<= 1) ;;
        v.resize(2*cap, unit());
        for (int i = 0; i < n; i++) v[cap+i] = gen(i);
        for (int i = cap-1; i >= 1; i--) v[i] = merge(v[2*i],v[2*i+1]);
    }
    void init(int n) { init(n, [&](int) { return unit(); }); }
    void init(int n, Value const& x) { init(n, [&](int) { return x; }); }
    void init(vector<Value> const& v) { init(v.size(), [&](int i) { return v[i]; }); }
    int size() const { return n; }

    void set(int i, Value const& x) {
        assert(0 <= i); assert(i < size());
        i += cap; v[i] = x;
        while (i > 1) i >>= 1, v[i] = merge(v[2*i],v[2*i+1]);
    }
    Value operator[](int i) const { return get(i); }
    Value get(int i) const {
        assert(0 <= i); assert(i < size());
        return v[cap + i];
    }
    // [l,r)
    Value get(int l, int r) const {
        assert(0 <= l); assert(l <= r); assert(r <= size());
        Value x = unit(), y = unit();
        for (l += cap, r += cap; l < r; l >>= 1, r >>= 1) {
            if (l&1) x = merge(x, v[l++]);
            if (r&1) y = merge(v[--r], y);
        }
        return merge(x,y);
    }
    vector<Value> dat() const {
        vector<Value> ret(size());
        for (int i = 0; i < size(); i++) ret[i] = get(i);
        return ret;
    }
};
// <<<
struct RangeMax {
    using Value = int;
    constexpr static Value unit() { return -INF; }
    constexpr static Value merge(Value x, Value y) { return max(x,y); }
};

int32_t main() {
    int n; cin >> n;
    vector<int> a(n); cin >> a;
    rep (i,n) a[i] -= i;
    dump(n,a);

    auto calc = [&]() {
        vector<int> idx(n);
        iota(all(idx),0);
        sort(all(idx), [&](int i, int j) { return mp(a[i],i) < mp(a[j],j); });

        vector<int> b(n);
        Segtree<RangeMax> seg(n);
        for (int i : idx) {
            b[i] = max(0LL,seg.get(0,i)) + 1;
            seg.set(i,b[i]);
        }
        return b;
    };

    vector<int> b[2];
    rep (i,2) {
        b[i] = calc();
        for (int &x : a) x = -x;
        reverse(all(a));
    }
    reverse(all(b[1]));
    dump(b[0]);
    dump(b[1]);

    int ans = INF;
    chmin(ans, n-min(n,1+*max_element(all(b[0]))));

    map<int,int> m;
    rep (i,n-1) {
        if (m.count(a[i+1]+1)) {
            chmin(ans, n-1-(m[a[i+1]+1] + b[1][i+1]));
        }
        chmax(m[a[i]], b[0][i]);
    }

    cout << ans << endl;

}


#ifndef BZ
#pragma GCC optimize "-O3"
#endif
#include <bits/stdc++.h>

#define FASTIO

#ifdef FASTIO
#define scanf abacaba
#define printf abacaba
#endif

typedef long long ll;
typedef long long llong;
typedef long double ld;
typedef unsigned long long ull;

using namespace std;

/*
ll pw(ll a, ll b) {
	ll ans = 1; while (b) {
		while (!(b & 1)) b >>= 1, a = (a * a) % MOD;
		ans = (ans * a) % MOD, --b;
	} return ans;
}
*/

const ll INF = 1e10;
const int MAXN = 220000;
int n;
ll a[MAXN];

set<pair<ll, int> > ss;

ll go[MAXN];
int gl[MAXN];
int gr[MAXN];

int main() {
#ifdef FASTIO
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#endif
	cin >> n;
	for (int i = 0; i < n; ++i)
		cin >> a[i], a[i] -= i;
	for (int i = 0; i <= n; ++i)
		go[i] = INF;
	go[0] = -INF;
	for (int i = 0; i < n; ++i) {
		int x = upper_bound(go, go + n, a[i]) - go;
		go[x] = a[i];
		gl[i] = x;
	}
	for (int i = 0; i <= n; ++i)
		go[i] = INF;
	go[0] = -INF;
	for (int i = n - 1; i >= 0; --i) {
		int x = upper_bound(go, go + n, -a[i]) - go;
		go[x] = -a[i];
		gr[i] = x;
	}
	int ans = 0;
	for (int i = 0; i < n; ++i) {
		ans = max(ans, gr[i]);
		auto it = ss.lower_bound(make_pair(a[i] + 2, 0));
		if (it != ss.begin()) {
			--it;
			ans = max(ans, it->second + gr[i]);
		}
		if (i >= 1) {
			it = ss.lower_bound(make_pair(a[i - 1] + 1, 0));
			if (it != ss.begin() && prev(it)->second >= gl[i - 1])
				continue;
			it = ss.insert(make_pair(a[i - 1], gl[i - 1])).first;
			while (next(it) != ss.end() && next(it)->second <= gl[i - 1])
				ss.erase(next(it));
		}
	}
	cout << max(0, n - ans - 1) << "\n";
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

using ll = long long;

template<typename T> struct segtree {

    T merge(T x, T y) {
	return max(x,y);
    }
    int n;
    vector<T> t;
    void init(int n) {
	n += 10;
	this->n = n;
	t.assign(n*4, 0);
    }

    void upd(int v, int tl, int tr, int i, T dx) {
	if (tl == tr) {
	    t[v] = merge(t[v], dx);
	} else {
	    int tm = (tl+tr)/2;
	    if (i<=tm) {
		upd(2*v,tl,tm,i,dx);
	    } else {
		upd(2*v+1,tm+1,tr,i,dx);
	    }
	    t[v] = merge(t[2*v], t[2*v+1]);
	}
    }

    T qry(int v, int tl, int tr, int l, int r) {
	if (l>tr || r<tl) {
	    return 0;
	}
	if (l <= tl && tr <= r) {
	    return t[v];
	}
	int tm = (tl+tr)/2;
	return merge(qry(2*v,tl,tm,l,r), qry(2*v+1,tm+1,tr,l,r));
    }
};

const int maxn = 1e6 + 5;

int n, N;
int a[maxn];

segtree<int> tree;

int pre[maxn], suf[maxn];

vector<int> ord;

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

    cin>>n;
    for (int i=1; i<=n; i++) {
	cin>>a[i];
	a[i] -= i;
	ord.push_back(a[i]);
    }
    a[0] = -1e9;

    ord.push_back(-2e9);
    sort(ord.begin(),ord.end());
    ord.erase(unique(ord.begin(),ord.end()),ord.end());

    N = (int)ord.size() - 1;

    auto get = [&](int x) {
	int idx = std::lower_bound(ord.begin(),ord.end(),x)-ord.begin();
	return idx;
    };

    tree.init(N);

    for (int i=1; i<=n; i++) {
	int cc = get(a[i]);
	pre[i] = tree.qry(1,1,N,1,cc)+1;
	tree.upd(1,1,N,cc,pre[i]);
    }

    int ans = n-1;
    tree.init(N);
    //assert(tree.qry(1,1,N,1,N)==0);

    for (int i=n; i>=1; i--) {
	// delete a[i]
	int cc = get(a[i-1]-1);
	int cur = pre[i-1] + tree.qry(1,1,N,cc,N);

	int res = n-1-cur;
	ans = min(ans, res);

	//cout<<i<<": "<<res<<endl;

	cc = get(a[i]);

	int resi = tree.qry(1,1,N,cc,N)+1;
	tree.upd(1,1,N,cc,resi);
    }

    cout<<ans<<endl;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

using ll = long long;

template<typename T> struct segtree {

    T merge(T x, T y) {
	return max(x,y);
    }
    int n;
    vector<T> t;
    void init(int n) {
	n += 10;
	this->n = n;
	t.assign(n*4, 0);
    }

    void upd(int v, int tl, int tr, int i, T dx) {
	if (tl == tr) {
	    t[v] = merge(t[v], dx);
	} else {
	    int tm = (tl+tr)/2;
	    if (i<=tm) {
		upd(2*v,tl,tm,i,dx);
	    } else {
		upd(2*v+1,tm+1,tr,i,dx);
	    }
	    t[v] = merge(t[2*v], t[2*v+1]);
	}
    }

    T qry(int v, int tl, int tr, int l, int r) {
	if (l>tr || r<tl) {
	    return 0;
	}
	if (l <= tl && tr <= r) {
	    return t[v];
	}
	int tm = (tl+tr)/2;
	return merge(qry(2*v,tl,tm,l,r), qry(2*v+1,tm+1,tr,l,r));
    }
};

const int maxn = 1e6 + 5;

int n, N;
int a[maxn];

segtree<int> tree;

int pre[maxn], suf[maxn];

vector<int> ord;

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

    cin>>n;
    for (int i=1; i<=n; i++) {
	cin>>a[i];
	a[i] -= i;
	ord.push_back(a[i]);
    }

    ord.push_back(-2e9);
    sort(ord.begin(),ord.end());
    ord.erase(unique(ord.begin(),ord.end()),ord.end());

    N = (int)ord.size() - 1;

    for (int i=1; i<=n; i++) {
	a[i] = std::lower_bound(ord.begin(),ord.end(),a[i])-ord.begin();
    }

    tree.init(N);

    for (int i=1; i<=n; i++) {
	pre[i] = tree.qry(1,1,N,1,a[i])+1;
	tree.upd(1,1,N,a[i],pre[i]);
    }

    int ans = n-1-pre[n];
    tree.init(N);

    tree.upd(1,1,N,a[n],1);

    for (int i=n-1; i>1; i--) {
	// delete a[i]
	int cur = pre[i-1] + tree.qry(1,1,N,a[i-1],N);
	ans = min(ans, n-1-cur);

	int resi = tree.qry(1,1,N,a[i],N)+1;
	tree.upd(1,1,N,a[i],resi);
    }

    cout<<ans<<endl;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

using ll = long long;

template<typename T> struct segtree {

    T merge(T x, T y) {
	return max(x,y);
    }
    int n;
    vector<T> t;
    void init(int n) {
	n += 10;
	this->n = n;
	t.assign(n*4, 0);
    }

    void upd(int v, int tl, int tr, int i, T dx) {
	if (tl == tr) {
	    t[v] = merge(t[v], dx);
	} else {
	    int tm = (tl+tr)/2;
	    if (i<=tm) {
		upd(2*v,tl,tm,i,dx);
	    } else {
		upd(2*v+1,tm+1,tr,i,dx);
	    }
	    t[v] = merge(t[2*v], t[2*v+1]);
	}
    }

    T qry(int v, int tl, int tr, int l, int r) {
	if (l>tr || r<tl) {
	    return 0;
	}
	if (l <= tl && tr <= r) {
	    return t[v];
	}
	int tm = (tl+tr)/2;
	return merge(qry(2*v,tl,tm,l,r), qry(2*v+1,tm+1,tr,l,r));
    }
};

const int maxn = 1e6 + 5;

int n, N;
int a[maxn];

segtree<int> tree;

int pre[maxn], suf[maxn];

vector<int> ord;

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

    cin>>n;
    for (int i=1; i<=n; i++) {
	cin>>a[i];
	a[i] -= i;
	ord.push_back(a[i]);
    }

    ord.push_back(-2e9);
    sort(ord.begin(),ord.end());
    ord.erase(unique(ord.begin(),ord.end()),ord.end());

    N = (int)ord.size() - 1;

    for (int i=1; i<=n; i++) {
	a[i] = std::lower_bound(ord.begin(),ord.end(),a[i])-ord.begin();
    }

    tree.init(N);

    for (int i=1; i<=n; i++) {
	pre[i] = tree.qry(1,1,N,1,a[i])+1;
	tree.upd(1,1,N,a[i],pre[i]);
    }

    int ans = n-1-pre[n];
    tree.init(N);

    for (int i=n; i>=1; i--) {
	// delete a[i]
	int cur = pre[i-1] + tree.qry(1,1,N,a[i-1],N);
	ans = min(ans, n-1-cur);

	int resi = tree.qry(1,1,N,a[i],N)+1;
	tree.upd(1,1,N,a[i],resi);
    }

    cout<<ans<<endl;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

using ll = long long;

template<typename T> struct segtree {

    T merge(T x, T y) {
	return max(x,y);
    }
    int n;
    vector<T> t;
    void init(int n) {
	n += 10;
	this->n = n;
	t.assign(n*4, 0);
    }

    void upd(int v, int tl, int tr, int i, T dx) {
	if (tl == tr) {
	    t[v] = merge(t[v], dx);
	} else {
	    int tm = (tl+tr)/2;
	    if (i<=tm) {
		upd(2*v,tl,tm,i,dx);
	    } else {
		upd(2*v+1,tm+1,tr,i,dx);
	    }
	    t[v] = merge(t[2*v], t[2*v+1]);
	}
    }

    T qry(int v, int tl, int tr, int l, int r) {
	if (l>tr || r<tl) {
	    return 0;
	}
	if (l <= tl && tr <= r) {
	    return t[v];
	}
	int tm = (tl+tr)/2;
	return merge(qry(2*v,tl,tm,l,r), qry(2*v+1,tm+1,tr,l,r));
    }
};

const int maxn = 1e6 + 5;

int n, N;
int a[maxn];

segtree<int> tree;

int pre[maxn], suf[maxn];

vector<int> ord;

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

    cin>>n;
    for (int i=1; i<=n; i++) {
	cin>>a[i];
	a[i] -= i;
	ord.push_back(a[i]);
    }

    ord.push_back(-2e9);
    sort(ord.begin(),ord.end());
    ord.erase(unique(ord.begin(),ord.end()),ord.end());

    N = (int)ord.size() - 1;

    auto get = [&](int x) {
	int idx = std::lower_bound(ord.begin(),ord.end(),x)-ord.begin();
	return idx;
    };

    tree.init(N);

    for (int i=1; i<=n; i++) {
	int cc = get(a[i]);
	pre[i] = tree.qry(1,1,N,1,cc)+1;
	tree.upd(1,1,N,cc,pre[i]);
    }

    int ans = n-1;
    tree.init(N);
    //assert(tree.qry(1,1,N,1,N)==0);

    for (int i=n; i>=1; i--) {
	// delete a[i]
	int cc = get(a[i-1]-1);
	int cur = pre[i-1] + tree.qry(1,1,N,cc,N);
	ans = min(ans, n-1-cur);

	cc = get(a[i]);

	int resi = tree.qry(1,1,N,cc,N)+1;
	tree.upd(1,1,N,cc,resi);
    }

    cout<<ans<<endl;

    return 0;
}


/* {{{ */ #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using vi = vector<int>;

namespace utils{
  constexpr bool use_stdio = false;
  ostream* out = &cout;
  FILE* stdio_out = stdout;
  const bool __ = [](){ if constexpr(!use_stdio){ ios_base::sync_with_stdio(false); cin.tie(nullptr);
    cout << fixed; cout << setprecision(12); cerr << fixed; cerr << setprecision(12); } return true; }();
  template<typename ...> using to_void = void;
  template<typename T, typename = void> struct is_container : false_type {};
  template<typename T> struct is_container<T, to_void<decltype(declval<T>().begin()), decltype(declval<T>().end())>> : true_type {};
  template<typename V, typename N> struct resize { V& v; N& n; resize(V& vv, N& nn) : v(vv), n(nn) {} ~resize() { v.resize(n); } };

  inline void rd(int& x) { if constexpr(use_stdio) scanf("%d", &x); else cin >> x; }
  inline void rd(long long& x) { if constexpr(use_stdio) scanf("%lld", &x); else cin >> x; }
  inline void rd(double& x) { if constexpr(use_stdio) scanf("%lf", &x); else cin >> x; }
  inline void rd(long double& x) { if constexpr(use_stdio){ double y; scanf("%lf", &y); x=y; } else cin >> x; }
  inline void rd(char& x) { if constexpr(use_stdio) scanf(" %c", &x); else cin >> x; }
  inline void rd(char* x) { if constexpr(use_stdio) scanf("%s", x); else cin >> x; }
  inline void rd(string& x) { if constexpr(use_stdio) assert(false); else cin >> x; }
  template<typename T, typename enable_if<!use_stdio && is_integral<T>::value>::type* = nullptr> inline void rd(T& x) { cin >> x; }
  template<typename T> inline void rd(T* x);
  template<typename T, typename enable_if<is_container<T>::value>::type* = nullptr> inline void rd(T& x);
  template<typename... Ts> inline void rd(tuple<Ts...>& x);
  template<typename V, typename N> inline void rd(const resize<V, N>& x);
  template<typename T, typename U> inline void rd(pair<T, U>& x) { rd(x.first); rd(x.second); }
  template<typename V, typename N> inline void rd(const resize<V, N>& x) { const_cast<V&>(x.v).resize(x.n); rd(x.v); }
  template<typename T, typename enable_if<is_container<T>::value>::type* = nullptr> inline void rd(T& x) { for(auto& v : x) rd(v); }
  template<typename T, typename U, typename... Ts> inline void rd(T&& t, U&& u, Ts&&... ts) {
    rd(forward<T>(t)); rd(forward<U>(u), forward<Ts>(ts)...); }
  template<typename... Ts> inline void rd(tuple<Ts...>& x) { static_assert(sizeof...(Ts) > 0);
    constexpr auto apply_rd = [](auto&&... xs) { rd(xs...); }; apply(apply_rd, x); }
  template<typename T> inline void rd(T* x) { rd(*x); }

  inline void prt(const int& x) { if constexpr(use_stdio) fprintf(stdio_out, "%d", x); else *out << x; }
  inline void prt(const long long& x) { if constexpr(use_stdio) fprintf(stdio_out, "%lld", x); else *out << x; }
  inline void prt(const double& x) { if constexpr(use_stdio) fprintf(stdio_out, "%.12f", x); else *out << x; }
  inline void prt(const long double& x) { if constexpr(use_stdio) fprintf(stdio_out, "%.12f", (double)x); else *out << x; }
  inline void prt(const char& x) { if constexpr(use_stdio) fprintf(stdio_out, "%c", x); else *out << x; }
  inline void prt(const char* x) { if constexpr(use_stdio) fprintf(stdio_out, "%s", x); else *out << x; }
  inline void prt(const string &x) { if constexpr(use_stdio) fprintf(stdio_out, "%s", x.c_str()); else *out << x; }
  template<typename T, typename enable_if<!use_stdio && is_integral<T>::value>::type* = nullptr> inline void prt(const T& x) { *out << x; }
  template<typename T, typename enable_if<is_container<T>::value>::type* = nullptr> inline void prt(const T& x);
  template<typename... Ts> inline void prt(const tuple<Ts...>& x);
  template<typename T, typename U> inline void prt(const pair<T, U>& x) { prt(x.first); prt(' '); prt(x.second); }
  template<typename T, typename enable_if<is_container<T>::value>::type* = nullptr> inline void prt(const T& x) {
    if (x.begin() != x.end()) { prt(*x.begin()); for(auto it = x.begin(); ++it != x.end(); ) { prt(' '); prt(*it); } } }
  template<typename T, typename U, typename... Ts> inline void prt(T&& t, U&& u, Ts&&... ts) {
    prt(forward<T>(t)); prt(' '); prt(forward<U>(u), forward<Ts>(ts)...); }
  template<typename... Ts> inline void prt(const tuple<Ts...>& x ) { static_assert(sizeof...(Ts) > 0);
    constexpr auto apply_prt = [](auto&&... xs) { prt(xs...); }; apply(apply_prt, x); }
  inline void wt() { prt('\n'); }
  template<typename... Ts> inline void wt(Ts&&... ts) { prt(forward<Ts>(ts)...); wt(); }

#ifdef MY_DEBUG_FLAG
  inline void enter_db() { if constexpr(use_stdio) stdio_out = stderr; else out = &cerr; }
  inline void leave_db() { if constexpr(use_stdio) stdio_out = stdout; else out = &cout; }
  inline void db() { enter_db(); prt('\n'); leave_db(); }
  template<typename... Ts> inline void db(Ts&&... ts) { enter_db(); prt(forward<Ts>(ts)...); wt(); leave_db(); }
#define db(...) utils::db("Debug(", #__VA_ARGS__, ") == (", __VA_ARGS__, ")")
#else
#define db(...)
#endif // define(MY_DEBUG_FLAG)
  constexpr int slen(char*s){ return (int) strlen(s); }
  void flush() { if constexpr(use_stdio) fflush(stdout); else cout << std::flush; }
} using utils::rd, utils::prt, utils::wt, utils::slen, utils::resize, utils::flush;

#define pb emplace_back
#define x first
#define y second
#define sz(a) ((int)(a).size())
#define rep(i,a,b) for(int i=(a); i<(b); i++)
#define dec(i,n,a) for(int i=(n); i>=(a); i--)
#define clr(a,v) memset(a, v, sizeof(a))
#define all(a) (a).begin(),(a).end() /* }}} */

constexpr int inf = 0x3f3f3f3f;
constexpr ld EPS = 1e-9;
constexpr int MAXN = 1e5 + 10;
constexpr int LOGN = 20;
constexpr int mod = 1000000007;

/* {{{ */ template<typename Node> struct segtree {
  int n;
  vector<Node> tree;
  vector<int> lc, rc;

  segtree(int N = 0, Node Zero = Node())
    : tree{Zero}, lc{0}, rc{0} { build(N); }

  int add_node(const Node& node, int resl = 0, int resr = 0) {
    tree.push_back(node);
    lc.push_back(resl);
    rc.push_back(resr);
    return (int) tree.size() - 1;
  }

  int add_node(Node&& node, int resl = 0, int resr = 0) {
    tree.push_back(move(node));
    lc.push_back(resl);
    rc.push_back(resr);
    return (int) tree.size() - 1;
  }

  template<typename E>
    int build(int l, int r, E* leafs) {
      if (l == r) return add_node(Node(leafs[l]));
      int mid = (l + r) >> 1;
      int resl = build(l, mid, leafs);
      int resr = build(mid + 1, r, leafs);
    }

  void build(int N) {
    n = N;
    tree.resize(1);
    lc.resize(1);
    rc.resize(1);
    tree.reserve(n << 1);
    lc.reserve(n << 1);
    rc.reserve(n << 1);
  }

  template<typename E> int build(const vector<E>& leafs) {
    build((int) leafs.size());
    return build(0, n - 1, leafs.data());
  }

  template<typename E> int build(const E* leafs, int N) {
    build(N);
    return build(0, n - 1, leafs);
  }

  template<typename... Ts> int upd(int b, int l, int r, int p, Ts&&... vals) {
    if (l == r) {
      Node node = tree[b];
      node(forward<Ts>(vals)...);
      return add_node(move(node));
    }
    int mid = (l + r) >> 1, resl = lc[b], resr = rc[b];
    if (p <= mid) resl = upd(resl, l, mid, p, forward<Ts>(vals)...);
    else resr = upd(resr, mid + 1, r, p, forward<Ts>(vals)...);
    return add_node(tree[resl] + tree[resr], resl, resr);
  }

  template<typename... Ts> int upd(int root, int p, Ts&&... vals) {
    assert(0 <= p && p < n);
    return upd(root, 0, n - 1, p, forward<Ts>(vals)...);
  }

  Node query(int b, int l, int r, int x, int y) {
    if (r < x || y < l) return tree[0];
    if (x <= l && r <= y) return tree[b];
    int mid = (l + r) >> 1;
    return query(lc[b], l, mid, x, y) + query(rc[b], mid + 1, r, x, y);
  }

  Node query(int root, int x, int y) {
    return query(root, 0, n, x, y);
  }
}; /* }}} */

struct Node {
  int val;
  Node (int x = 0) : val(x) {}
  Node operator+(Node a) { return Node(max(val, a.val)); }
  void operator()(int x) { val = max(val, x); }
  explicit operator int() { return val; }
};

segtree<Node> st;
int n;
vi vet, roots;

int main() {
  rd(n, resize(vet, n));
  rep(i,0,n) vet[i] -= i;
  vi ord = vet;
  rep(i,0,n) ord.pb(vet[i] + 1);
  sort(all(ord));
  roots.assign(n + 1, 0);
  int m = 2 * n;
  st.build(m);
  dec(i,n-1,0) {
    int v = (int) (lower_bound(all(ord), vet[i] + 1) - ord.begin());
    int q = (int) st.query(roots[i + 1], v, m) + 1;
    roots[i] = st.upd(roots[i + 1], v, q);
  }
  int ans = n - 1 - (int) st.query(roots[1], 0, m);
  int rootp = 0;
  rep(i,1,n) {
    int v = (int) (lower_bound(all(ord), vet[i - 1]) - ord.begin());
    int q = (int) st.query(rootp, 0, v) + 1;
    rootp = st.upd(rootp, v, q);
    ans = min(ans, n - 1 - q - (int) st.query(roots[i + 1], v, m));
  }
  wt(ans);
}


/* {{{ */ #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using vi = vector<int>;

namespace utils{
constexpr bool use_stdio = false;
ostream* out = &cout;
FILE* stdio_out = stdout;
const bool __ = [](){ if constexpr(!use_stdio){ ios_base::sync_with_stdio(false); cin.tie(nullptr);
  cout << fixed; cout << setprecision(12); cerr << fixed; cerr << setprecision(12); } return true; }();
template<typename ...> using to_void = void;
template<typename T, typename = void> struct is_container : false_type {};
template<typename T> struct is_container<T, to_void<decltype(declval<T>().begin()), decltype(declval<T>().end())>> : true_type {};
template<typename V, typename N> struct resize { V& v; N& n; resize(V& vv, N& nn) : v(vv), n(nn) {} ~resize() { v.resize(n); } };

inline void rd(int& x) { if constexpr(use_stdio) scanf("%d", &x); else cin >> x; }
inline void rd(long long& x) { if constexpr(use_stdio) scanf("%lld", &x); else cin >> x; }
inline void rd(double& x) { if constexpr(use_stdio) scanf("%lf", &x); else cin >> x; }
inline void rd(long double& x) { if constexpr(use_stdio){ double y; scanf("%lf", &y); x=y; } else cin >> x; }
inline void rd(char& x) { if constexpr(use_stdio) scanf(" %c", &x); else cin >> x; }
inline void rd(char* x) { if constexpr(use_stdio) scanf("%s", x); else cin >> x; }
inline void rd(string& x) { if constexpr(use_stdio) assert(false); else cin >> x; }
template<typename T, typename enable_if<!use_stdio && is_integral<T>::value>::type* = nullptr> inline void rd(T& x) { cin >> x; }
template<typename T> inline void rd(T* x);
template<typename T, typename enable_if<is_container<T>::value>::type* = nullptr> inline void rd(T& x);
template<typename... Ts> inline void rd(tuple<Ts...>& x);
template<typename V, typename N> inline void rd(const resize<V, N>& x);
template<typename T, typename U> inline void rd(pair<T, U>& x) { rd(x.first); rd(x.second); }
template<typename V, typename N> inline void rd(const resize<V, N>& x) { const_cast<V&>(x.v).resize(x.n); rd(x.v); }
template<typename T, typename enable_if<is_container<T>::value>::type* = nullptr> inline void rd(T& x) { for(auto& v : x) rd(v); }
template<typename T, typename U, typename... Ts> inline void rd(T&& t, U&& u, Ts&&... ts) {
  rd(forward<T>(t)); rd(forward<U>(u), forward<Ts>(ts)...); }
template<typename... Ts> inline void rd(tuple<Ts...>& x) { static_assert(sizeof...(Ts) > 0);
  constexpr auto apply_rd = [](auto&&... xs) { rd(xs...); }; apply(apply_rd, x); }
template<typename T> inline void rd(T* x) { rd(*x); }

inline void prt(const int& x) { if constexpr(use_stdio) fprintf(stdio_out, "%d", x); else *out << x; }
inline void prt(const long long& x) { if constexpr(use_stdio) fprintf(stdio_out, "%lld", x); else *out << x; }
inline void prt(const double& x) { if constexpr(use_stdio) fprintf(stdio_out, "%.12f", x); else *out << x; }
inline void prt(const long double& x) { if constexpr(use_stdio) fprintf(stdio_out, "%.12f", (double)x); else *out << x; }
inline void prt(const char& x) { if constexpr(use_stdio) fprintf(stdio_out, "%c", x); else *out << x; }
inline void prt(const char* x) { if constexpr(use_stdio) fprintf(stdio_out, "%s", x); else *out << x; }
inline void prt(const string &x) { if constexpr(use_stdio) fprintf(stdio_out, "%s", x.c_str()); else *out << x; }
template<typename T, typename enable_if<!use_stdio && is_integral<T>::value>::type* = nullptr> inline void prt(const T& x) { *out << x; }
template<typename T, typename enable_if<is_container<T>::value>::type* = nullptr> inline void prt(const T& x);
template<typename... Ts> inline void prt(const tuple<Ts...>& x);
template<typename T, typename U> inline void prt(const pair<T, U>& x) { prt(x.first); prt(' '); prt(x.second); }
template<typename T, typename enable_if<is_container<T>::value>::type* = nullptr> inline void prt(const T& x) {
  if (x.begin() != x.end()) { prt(*x.begin()); for(auto it = x.begin(); ++it != x.end(); ) { prt(' '); prt(*it); } } }
template<typename T, typename U, typename... Ts> inline void prt(T&& t, U&& u, Ts&&... ts) {
  prt(forward<T>(t)); prt(' '); prt(forward<U>(u), forward<Ts>(ts)...); }
template<typename... Ts> inline void prt(const tuple<Ts...>& x ) { static_assert(sizeof...(Ts) > 0);
  constexpr auto apply_prt = [](auto&&... xs) { prt(xs...); }; apply(apply_prt, x); }
inline void wt() { prt('\n'); }
template<typename... Ts> inline void wt(Ts&&... ts) { prt(forward<Ts>(ts)...); wt(); }

#ifdef MY_DEBUG_FLAG
inline void enter_db() { if constexpr(use_stdio) stdio_out = stderr; else out = &cerr; }
inline void leave_db() { if constexpr(use_stdio) stdio_out = stdout; else out = &cout; }
inline void db() { enter_db(); prt('\n'); leave_db(); }
template<typename... Ts> inline void db(Ts&&... ts) { enter_db(); prt(forward<Ts>(ts)...); wt(); leave_db(); }
#define db(...) utils::db("Debug(", #__VA_ARGS__, ") == (", __VA_ARGS__, ")")
#else
#define db(...)
#endif // define(MY_DEBUG_FLAG)
constexpr int slen(char*s){ return (int) strlen(s); }
void flush() { if constexpr(use_stdio) fflush(stdout); else cout << std::flush; }
} using utils::rd, utils::prt, utils::wt, utils::slen, utils::resize, utils::flush;

#define pb emplace_back
#define x first
#define y second
#define sz(a) ((int)(a).size())
#define rep(i,a,b) for(int i=(a); i<(b); i++)
#define dec(i,n,a) for(int i=(n); i>=(a); i--)
#define clr(a,v) memset(a, v, sizeof(a))
#define all(a) (a).begin(),(a).end() /* }}} */

constexpr int inf = 0x3f3f3f3f;
constexpr ld EPS = 1e-9;
constexpr int MAXN = 1e5 + 10;
constexpr int LOGN = 20;
constexpr int mod = 1000000007;

struct Node {
  int v, cl, cr;
};

Node st[MAXN * LOGN * 8];
int ptr = 1;

int upd(int b, int l, int r, int p, int v) {
  if (p < l || r < p) return b;
  if (l == r) {
    st[ptr].v = max(st[b].v, v);
    return ptr++;
  }
  int md = (l + r) >> 1;
  int cl = upd(st[b].cl, l, md, p, v);
  int cr = upd(st[b].cr, md+1, r, p, v);
  st[ptr] = {max(st[cl].v, st[cr].v), cl, cr};
  return ptr++;
}

int query(int b, int l, int r, int x, int y) {
  if (y < l || r < x || !b) return 0;
  if (x <= l && r <= y) {
    return st[b].v;
  }
  int md = (l + r) >> 1;
  return max(query(st[b].cl, l, md, x, y), query(st[b].cr, md+1, r, x, y));
}

int n;
vi vet, roots;

int main() {
  rd(n, resize(vet, n));
  rep(i,0,n) vet[i] -= i;
  vi ord = vet;
  rep(i,0,n) ord.pb(vet[i] + 1);
  sort(all(ord));
  roots.assign(n + 1, 0);
  dec(i,n-1,0) {
    int v = (int) (lower_bound(all(ord), vet[i] + 1) - ord.begin());
    int q = query(roots[i + 1], 0, 2 * n, v, 2 * n) + 1;
    roots[i] = upd(roots[i + 1], 0, 2 * n, v, q);
  }
  int ans = n - 1 - query(roots[1], 0, 2 * n, 0, 2 * n);
  int rootp = 0;
  rep(i,1,n) {
    int v = (int) (lower_bound(all(ord), vet[i - 1]) - ord.begin());
    int q = query(rootp, 0, 2 * n, 0, v) + 1;
    rootp = upd(rootp, 0, 2 * n, v, q);
    ans = min(ans, n - 1 - q - query(roots[i + 1], 0, 2 * n, v, 2 * n));
  }
  wt(ans);
}