Problem:
Score : 500 points

Problem Statement

You are given a sequence (P_1,P_2,...,P_N) which is a permutation of the integers from 1 through N.
You would like to sort this sequence in ascending order by repeating the following operation:

Choose an element in the sequence and move it to the beginning or the end of the sequence.

Find the minimum number of operations required.
It can be proved that it is actually possible to sort the sequence using this operation.

Constraints

1 \leq N \leq 2\times 10^5

(P_1,P_2,...,P_N) is a permutation of (1,2,...,N).

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
P_1
:
P_N

Output

Print the minimum number of operations required.

Sample Input 1

4
1
3
2
4

Sample Output 1

2

For example, the sequence can be sorted in ascending order as follows:

Move 2 to the beginning. The sequence is now (2,1,3,4).

Move 1 to the beginning. The sequence is now (1,2,3,4).

Sample Input 2

6
3
2
5
1
4
6

Sample Output 2

4

Sample Input 3

8
6
3
1
2
7
4
8
5

Sample Output 3

5

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#pragma GCC optimize ("O3")
#include "bits/stdc++.h"

using namespace std;
using ll = long long int;

#define debug(v) {printf("L%d %s > ",__LINE__,#v);cout<<(v)<<endl;}
#define debugv(v) {printf("L%d %s > ",__LINE__,#v);for(auto e:(v)){cout<<e<<" ";}cout<<endl;}
#define debuga(m,w) {printf("L%d %s > ",__LINE__,#m);for(int x=0;x<(w);x++){cout<<(m)[x]<<" ";}cout<<endl;}
#define debugaa(m,h,w) {printf("L%d %s >\n",__LINE__,#m);for(int y=0;y<(h);y++){for(int x=0;x<(w);x++){cout<<(m)[y][x]<<" ";}cout<<endl;}}
#define ALL(v) (v).begin(),(v).end()
#define repeat(cnt,l) for(remove_const<decltype(l)>::type cnt=0;(cnt)<(l);++(cnt))
#define rrepeat(cnt,l) for(auto cnt=(l)-1;0<=(cnt);--(cnt))
#define iterate(cnt,b,e) for(auto cnt=(b);(cnt)!=(e);++(cnt))
#define diterate(cnt,b,e) for(auto cnt=(b);(cnt)!=(e);--(cnt))
const ll MD = 1000000007ll; const long double PI = 3.1415926535897932384626433832795L;
inline void assert_call(bool assertion, function<void()> f) { if (!assertion) { cerr << "assertion fault:" << endl; f(); abort(); } }
template<typename T1, typename T2> inline ostream& operator <<(ostream &o, const pair<T1, T2> p) { o << '(' << p.first << ':' << p.second << ')'; return o; }
template<typename Vec> inline ostream& _ostream_vecprint(ostream &o, const Vec& p) { o << '['; for (auto& e : p) o << e << ','; o << ']'; return o; }
template<typename T> inline ostream& operator<<(ostream& o, const vector<T>& v) { return _ostream_vecprint(o, v); }
template<typename T, size_t S> inline ostream& operator<<(ostream& o, const array<T, S>& v) { return _ostream_vecprint(o, v); }
template<typename T> inline T& maxset(T& to, const T& val) { return to = max(to, val); }
template<typename T> inline T& minset(T& to, const T& val) { return to = min(to, val); }
void bye(string s, int code = 0) { cout << s << endl; exit(code); }
mt19937_64 randdev(8901016);
template<typename T> inline T rand(T l, T h) { return uniform_int_distribution<T>(l, h)(randdev); }
template<> inline double rand<double>(double l, double h) { return uniform_real_distribution<double>(l, h)(randdev); }
template<> inline float rand<float>(float l, float h) { return uniform_real_distribution<float>(l, h)(randdev); }

#if defined(_WIN32) || defined(_WIN64)
#define getchar_unlocked _getchar_nolock
#define putchar_unlocked _putchar_nolock
#elif defined(__GNUC__)
#else
#define getchar_unlocked getchar
#define putchar_unlocked putchar
#endif
namespace {
#define isvisiblechar(c) (0x21<=(c)&&(c)<=0x7E)
    class MaiScanner {
    public:
        template<typename T> void input_integer(T& var) {
            var = 0; T sign = 1;
            int cc = getchar_unlocked();
            for (; cc<'0' || '9'<cc; cc = getchar_unlocked())
                if (cc == '-') sign = -1;
            for (; '0' <= cc && cc <= '9'; cc = getchar_unlocked())
                var = (var << 3) + (var << 1) + cc - '0';
            var = var * sign;
        }
        inline int c() { return getchar_unlocked(); }
        inline MaiScanner& operator>>(int& var) { input_integer<int>(var); return *this; }
        inline MaiScanner& operator>>(long long& var) { input_integer<long long>(var); return *this; }
        inline MaiScanner& operator>>(string& var) {
            int cc = getchar_unlocked();
            for (; !isvisiblechar(cc); cc = getchar_unlocked());
            for (; isvisiblechar(cc); cc = getchar_unlocked())
                var.push_back(cc);
            return *this;
        }
        template<typename IT> void in(IT begin, IT end) { for (auto it = begin; it != end; ++it) *this >> *it; }
    };
    class MaiPrinter {
    public:
        template<typename T>
        void output_integer(T var) {
            if (var == 0) { putchar_unlocked('0'); return; }
            if (var < 0)
                putchar_unlocked('-'),
                var = -var;
            char stack[32]; int stack_p = 0;
            while (var)
                stack[stack_p++] = '0' + (var % 10),
                var /= 10;
            while (stack_p)
                putchar_unlocked(stack[--stack_p]);
        }
        inline MaiPrinter& operator<<(char c) { putchar_unlocked(c); return *this; }
        inline MaiPrinter& operator<<(int var) { output_integer<int>(var); return *this; }
        inline MaiPrinter& operator<<(long long var) { output_integer<long long>(var); return *this; }
        inline MaiPrinter& operator<<(char* str_p) { while (*str_p) putchar_unlocked(*(str_p++)); return *this; }
        inline MaiPrinter& operator<<(const string& str) {
            const char* p = str.c_str();
            const char* l = p + str.size();
            while (p < l) putchar_unlocked(*p++);
            return *this;
        }
        template<typename IT> void join(IT begin, IT end, char sep = ' ') { for (bool b = 0; begin != end; ++begin, b = 1) b ? *this << sep << *begin : *this << *begin; }
    };
}
MaiScanner scanner;
MaiPrinter printer;

template<typename T>
//typedef ll T;
class SegmentTree {
    int size_;
    vector<T> valdata_;
    vector<T> addtree_;
    vector<T> maxtree_;

    int _geti(const vector<T>& v, int idx) const {
        if (size_ - 1 <= idx) return (idx - size_ + 1);
        // if (idx < 0) return idx;
        return v[idx];
    }
public:

    SegmentTree(int n) {
        size_ = 8;
        while (size_ < n) size_ <<= 1;
        maxtree_.resize(size_);
        valdata_.resize(size_);
        addtree_.resize(size_);
        flat();
    }

    // tree初期化
    void flat() {
        for (int i = size_ - 2; 0 <= i; --i) {
            int c = 2 * i + 1;
            if (size_ - 1 <= c) {
                maxtree_[i] = c - size_ + 1;
            }
            else {
                maxtree_[i] = maxtree_[c];
            }
        }
    }

    // addtreeを0にして，valdataに加算する．
    // void apply(T sum = 0, int ptr = 0) {
    //     if (size_ - 1 <= ptr) {
    //         valdata_[ptr - size_ + 1] += sum;
    //     }
    //     else {
    //         sum += addtree_[ptr];
    //         apply(sum, ptr * 2 + 1);
    //         apply(sum, ptr * 2 + 2);
    //         addtree_[ptr] = 0;
    //     }
    // }

    void fill(T val) {
        std::fill(valdata_.begin(), valdata_.end(), val);
        std::fill(addtree_.begin(), addtree_.end(), 0);
        flat();
    }

    // T operator[](int index) const {
    //     
    // }

    T get_val(int index) const {
        T sum = valdata_[index];
        index += size_ - 1;
        while (0 < index) {
            index = (index - 1) / 2; // 親へ移動
            sum += addtree_[index];
        }
        return sum;
    }

    void set_val(int index, const T e) {
        valdata_[index] = e;

        for (int i = index + size_ - 1; 0 < i;) {
            i = (i - 1) / 2; // 親へ移動
            valdata_[index] -= addtree_[i];
        }
        index += size_ - 1;
        while (0 < index) {
            index = (index - 1) / 2; // 親へ移動
            int c1 = index * 2 + 1;
            int c2 = index * 2 + 2;
            int i1, i2;
            i1 = _geti(maxtree_, c1);
            i2 = _geti(maxtree_, c2);
            maxtree_[index] = get_val(i1) > get_val(i2) ? i1 : i2;
        }
    }

    void _add_valrange(int begin, int end, const T e, int ptr, int rangebegin, int rangeend) {

        if (rangeend <= begin || end <= rangebegin) return;
        if (begin <= rangebegin && rangeend <= end) {
            if (size_ - 1 <= ptr)
                valdata_[ptr - size_ + 1] += e;
            else
                addtree_[ptr] += e;
            return;
        }

        int rangemid = (rangebegin + rangeend) / 2;
        _add_valrange(begin, end, e, ptr * 2 + 1, rangebegin, rangemid);
        _add_valrange(begin, end, e, ptr * 2 + 2, rangemid, rangeend);

        int i1, i2;
        i1 = _geti(maxtree_, ptr * 2 + 1);
        i2 = _geti(maxtree_, ptr * 2 + 2);
        maxtree_[ptr] = get_val(i1) > get_val(i2) ? i1 : i2;
    }

    int _get_maxrangeIdx(int begin, int end, int ptr, int rangebegin, int rangeend) const {

        if (rangeend <= begin || end <= rangebegin) return begin; // note:範囲外なら適当な範囲内のindexを返す
        if (begin <= rangebegin && rangeend <= end) return _geti(maxtree_, ptr);

        int rangemid = (rangebegin + rangeend) / 2;
        int l = _get_maxrangeIdx(begin, end, ptr * 2 + 1, rangebegin, rangemid);
        int r = _get_maxrangeIdx(begin, end, ptr * 2 + 2, rangemid, rangeend);

        if (get_val(l) >= get_val(r))
            return l;
        else
            return r;
    }

    inline void add_valrange(int begin, int end, const T e) {
        _add_valrange(begin, end, e, 0, 0, size_);
    }

    inline int get_maxrangeIdx(int begin, int end) const {
        return _get_maxrangeIdx(begin, end, 0, 0, size_);
    }

    inline T get_maxrange(int begin, int end) {
        return get_val(_get_maxrangeIdx(begin, end, 0, 0, size_));
    }
};


/*

逆シミュレート？
1..Nが並んでいる
先頭の要素または末尾の要素を自由な位置に移動させる

*/

int N;

int pp[200010], qq[200010];

int ans[200010];

int main() {
    scanner >> N;
    scanner.in(pp, pp + N);
    repeat(i, N) pp[i]--, qq[pp[i]] = i;

    // SegmentTree<int> segt(N);
    // 
    // int lis = 0;
    // 
    // repeat(i, N) {
    //     int v = segt.get_maxrange(0, pp[i] + 1);
    //     segt.set_val(v, v + 1);
    //     maxset(lis, v);
    // }
    // 
    // cout << lis << endl;
    
    repeat(i, N) {
        if (pp[i] < i) {
            ans[i] = pp[i]+1;
        }
    }
    rrepeat(i, N) {
        if (i < pp[i]) {
            minset(ans[i], N-pp[i]);
        }
    }
    
    int best = 0;
    repeat(i, N) maxset(best, ans[i]);
    
    cout << best << endl;

    

    return 0;
}