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

typedef long long LL;
typedef long double LD;
typedef pair < int, int > PII;
typedef pair < LL, LL > PLL;
typedef pair < LD, LD > PDD;

#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()
#define dbl(k, x) fixed << setprecision(k) << (x)

template < typename _T > inline void _DBG(const char *s, _T x) { cerr << s << " = " << x << "\n"; }
template < typename _T, typename... args > void _DBG(const char *s, _T x, args... a) { while(*s != ',') cerr << *s++; cerr << " = " << x << ','; _DBG(s + 1, a...); }

#ifdef LOCAL
#define _upgrade ios_base::sync_with_stdio(0);
#define DBG(...) _DBG(#__VA_ARGS__, __VA_ARGS__)
#else
#define _upgrade ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define DBG(...) (__VA_ARGS__)
#define cerr if(0) cout
#endif

// ********************** CODE ********************** //

struct SegmentTree { // (+, max)
    const static int MAX = 1 << 20;
    LL INF = 1e18 + 7;
    vector < PLL > tree;
    vector < LL > lazy;
    SegmentTree()
    {
        tree.resize(2 * MAX, {0, 0}), lazy.resize(2 * MAX, 0);
        for(int i = 0; i <= MAX - 1; i++)
            tree[i + MAX].second = i;
        for(int i = MAX - 1; i; i--)
            tree[i] = max(tree[2 * i], tree[2 * i + 1]); // (*)
    }
    inline void propagate(int node, int l, int r)
    {
        if(!lazy[node]) return;
        tree[node].first += lazy[node];
        if(l != r)
        {
            lazy[2 * node] += lazy[node];
            lazy[2 * node + 1] += lazy[node];
        }
        lazy[node] = 0;
    }
    void update(int a, int b, LL val, int node = 1, int l = 0, int r = MAX - 1)
    {
        propagate(node, l, r);
        if(b < l || r < a) return;
        if(a <= l && r <= b)
            lazy[node] += val, propagate(node, l, r);
        else
        {
            update(a, b, val, 2 * node, l, (l + r) / 2);
            update(a, b, val, 2 * node + 1, (l + r) / 2 + 1, r);
            tree[node] = max(tree[2 * node], tree[2 * node + 1]); // (*)
        }
    }
    PLL query(int a, int b, int node = 1, int l = 0, int r = MAX - 1)
    {
        propagate(node, l, r);
        if(b < l || r < a) return {-INF, 0}; // (*)
        if(a <= l && r <= b) return tree[node];
        return max(query(a, b, 2 * node, l, (l + r) / 2), query(a, b, 2 * node + 1, (l + r) / 2 + 1, r)); // (*)
    }
};

const LL INF = 1e18 + 7;

const int N = 1 << 18;

int n, T[N], tmp[N], prz, whe[N];
vector < int > lp, rp;
vector < int > G[N];
int A[N], sz[N], root;

PII treem[2 * N];

PII query_min(int a, int b)
{
    a += N, b += N;
    PII res = min(treem[a], treem[b]);
    while(a / 2 != b / 2)
    {
        if(a % 2 == 0) res = min(res, treem[a + 1]);
        if(b % 2 == 1) res = min(res, treem[b - 1]);
        a /= 2, b /= 2;
    }
    return res;
}

int build(int a, int b)
{
    if(a >= b) return a;
    PII p = query_min(a, b);
    if(a < p.second)
    {
        PII l = query_min(a, p.second - 1);
        G[p.second].push_back(l.second);
        build(a, p.second - 1);
    }
    if(p.second < b)
    {
        PII r = query_min(p.second + 1, b);
        G[p.second].push_back(r.second);
        build(p.second + 1, b);
    }
    return p.second;
}

int cntt = 1;

int dfs(int v)
{
    A[cntt++] = v;
    for(auto u: G[v])
        sz[v] += dfs(u);

    return ++sz[v];
}

SegmentTree treel, treer;

int main()
{
    _upgrade

    cin >> n;
    for(int i = 1; i <= n; i++)
        cin >> T[i];

    if(n == 1)
    {
        cout << "0 0\n";
        return 0;
    }

    for(int i = 1; i <= n; i++)
    {
        if(T[i] == 1)
        {
            prz = i;
            int cnt = 1;
            for(int j = i + 1; j <= n; j++)
                tmp[cnt++] = T[j];
            for(int j = 1; j <= i; j++)
                tmp[cnt++] = T[j];
            for(int j = 1; j <= n; j++)
                T[j] = tmp[j];
            break;
        }
    }

    for(int i = 1; i < n; i++)
        treem[i + N] = {T[i], i};
    for(int i = N - 1; i; i--)
        treem[i] = min(treem[2 * i], treem[2 * i + 1]);

    build(1, n - 1);
    for(int i = 1; i < n; i++)
    {
        whe[T[i]] = i;
    }
    root = whe[2];
    dfs(root);

    for(int i = 1; i < n; i++)
    {
        treer.update(i, i, -INF);
        treel.update(i, i + sz[i] - 1, 1);
    }

    int dep = max(treel.query(1, n - 1).first, treer.query(1, n - 1).first), bestp = 0;

    for(int p = 1; p < n; p++)
    {
        int x = whe[T[p]];
        treel.update(x, x, -INF);
        treel.update(x, x + sz[x] - 1, -1);

        treer.update(x, x, INF);
        treer.update(x, x + sz[x] - 1, 1);

        int tdep = max(treel.query(1, n - 1).first, treer.query(1, n - 1).first);
        if(tdep < dep)
        {
            dep = tdep;
            bestp = p;
        }
    }

    cout << dep + 1 << " " << (bestp + prz) % n << "\n";

	return 0;
}


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

typedef long long LL;
typedef long double LD;
typedef pair < int, int > PII;
typedef pair < LL, LL > PLL;
typedef pair < LD, LD > PDD;

#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()
#define dbl(k, x) fixed << setprecision(k) << (x)

template < typename _T > inline void _DBG(const char *s, _T x) { cerr << s << " = " << x << "\n"; }
template < typename _T, typename... args > void _DBG(const char *s, _T x, args... a) { while(*s != ',') cerr << *s++; cerr << " = " << x << ','; _DBG(s + 1, a...); }

#ifdef LOCAL
#define _upgrade ios_base::sync_with_stdio(0);
#define DBG(...) _DBG(#__VA_ARGS__, __VA_ARGS__)
#else
#define _upgrade ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define DBG(...) (__VA_ARGS__)
#define cerr if(0) cout
#endif

// ********************** CODE ********************** //

struct SegmentTree { // (+, max)
    const static int MAX = 1 << 20;
    LL INF = 1e18 + 7;
    vector < PLL > tree;
    vector < LL > lazy;
    SegmentTree()
    {
        tree.resize(2 * MAX, {0, 0}), lazy.resize(2 * MAX, 0);
        for(int i = 0; i <= MAX - 1; i++)
            tree[i + MAX].second = i;
        for(int i = MAX - 1; i; i--)
            tree[i] = max(tree[2 * i], tree[2 * i + 1]); // (*)
    }
    inline void propagate(int node, int l, int r)
    {
        if(!lazy[node]) return;
        tree[node].first += lazy[node];
        if(l != r)
        {
            lazy[2 * node] += lazy[node];
            lazy[2 * node + 1] += lazy[node];
        }
        lazy[node] = 0;
    }
    void update(int a, int b, LL val, int node = 1, int l = 0, int r = MAX - 1)
    {
        propagate(node, l, r);
        if(b < l || r < a) return;
        if(a <= l && r <= b)
            lazy[node] += val, propagate(node, l, r);
        else
        {
            update(a, b, val, 2 * node, l, (l + r) / 2);
            update(a, b, val, 2 * node + 1, (l + r) / 2 + 1, r);
            tree[node] = max(tree[2 * node], tree[2 * node + 1]); // (*)
        }
    }
    PLL query(int a, int b, int node = 1, int l = 0, int r = MAX - 1)
    {
        propagate(node, l, r);
        if(b < l || r < a) return {-INF, 0}; // (*)
        if(a <= l && r <= b) return tree[node];
        return max(query(a, b, 2 * node, l, (l + r) / 2), query(a, b, 2 * node + 1, (l + r) / 2 + 1, r)); // (*)
    }
};

const LL INF = 1e18 + 7;

const int N = 1 << 18;

int n, T[N], tmp[N], prz, whe[N];
vector < int > lp, rp;
vector < int > G[N];
int A[N], sz[N], root;

PII treem[2 * N];

PII query_min(int a, int b)
{
    a += N, b += N;
    PII res = min(treem[a], treem[b]);
    while(a / 2 != b / 2)
    {
        if(a % 2 == 0) res = min(res, treem[a + 1]);
        if(b % 2 == 1) res = min(res, treem[b - 1]);
        a /= 2, b /= 2;
    }
    return res;
}

int build(int a, int b)
{
    if(a >= b) return a;
    PII p = query_min(a, b);
    if(a < p.second)
    {
        PII l = query_min(a, p.second - 1);
        G[p.second].push_back(l.second);
        build(a, p.second - 1);
    }
    if(p.second < b)
    {
        PII r = query_min(p.second + 1, b);
        G[p.second].push_back(r.second);
        build(p.second + 1, b);
    }
    return p.second;
}

int cntt = 1;

int dfs(int v)
{
    A[v] = cntt++;
    for(auto u: G[v])
        sz[A[v]] += dfs(u);

    return ++sz[A[v]];
}

SegmentTree treel, treer;

int main()
{
    _upgrade

    cin >> n;
    for(int i = 1; i <= n; i++)
        cin >> T[i];

    if(n == 1)
    {
        cout << "1 0\n";
        return 0;
    }

    for(int i = 1; i <= n; i++)
    {
        if(T[i] == 1)
        {
            prz = i;
            int cnt = 1;
            for(int j = i + 1; j <= n; j++)
                tmp[cnt++] = T[j];
            for(int j = 1; j <= i; j++)
                tmp[cnt++] = T[j];
            for(int j = 1; j <= n; j++)
                T[j] = tmp[j];
            break;
        }
    }

    for(int i = 1; i < n; i++)
        treem[i + N] = {T[i], i};
    for(int i = N - 1; i; i--)
        treem[i] = min(treem[2 * i], treem[2 * i + 1]);

    build(1, n - 1);
    for(int i = 1; i < n; i++)
    {
        whe[T[i]] = i;
    }
    root = whe[2];
    dfs(root);

    for(int i = 1; i < n; i++)
    {
        treer.update(i, i, -INF);
        treel.update(i, i + sz[i] - 1, 1);
    }

    int dep = max(treel.query(1, n - 1).first, treer.query(1, n - 1).first), bestp = 0;

    for(int p = 1; p < n; p++)
    {
        int x = whe[T[p]];
        treel.update(A[x], A[x], -INF);
        treel.update(A[x], A[x] + sz[A[x]] - 1, -1);

        treer.update(A[x], A[x], INF);
        treer.update(A[x], A[x] + sz[A[x]] - 1, 1);

        int tdep = max(treel.query(1, n - 1).first, treer.query(1, n - 1).first);
        if(tdep < dep)
        {
            dep = tdep;
            bestp = p;
        }
    }

    cout << dep + 1 << " " << (bestp + prz) % n << "\n";

	return 0;
}


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

typedef long long LL;
typedef long double LD;
typedef pair < int, int > PII;
typedef pair < LL, LL > PLL;
typedef pair < LD, LD > PDD;

#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()
#define dbl(k, x) fixed << setprecision(k) << (x)

template < typename _T > inline void _DBG(const char *s, _T x) { cerr << s << " = " << x << "\n"; }
template < typename _T, typename... args > void _DBG(const char *s, _T x, args... a) { while(*s != ',') cerr << *s++; cerr << " = " << x << ','; _DBG(s + 1, a...); }

#ifdef LOCAL
#define _upgrade ios_base::sync_with_stdio(0);
#define DBG(...) _DBG(#__VA_ARGS__, __VA_ARGS__)
#else
#define _upgrade ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define DBG(...) (__VA_ARGS__)
#define cerr if(0) cout
#endif

// ********************** CODE ********************** //

struct SegmentTree { // (+, max)
    const static int MAX = 1 << 20;
    LL INF = 1e18 + 7;
    vector < PLL > tree;
    vector < LL > lazy;
    SegmentTree()
    {
        tree.resize(2 * MAX, {0, 0}), lazy.resize(2 * MAX, 0);
        for(int i = 0; i <= MAX - 1; i++)
            tree[i + MAX].second = i;
        for(int i = MAX - 1; i; i--)
            tree[i] = max(tree[2 * i], tree[2 * i + 1]); // (*)
    }
    inline void propagate(int node, int l, int r)
    {
        if(!lazy[node]) return;
        tree[node].first += lazy[node];
        if(l != r)
        {
            lazy[2 * node] += lazy[node];
            lazy[2 * node + 1] += lazy[node];
        }
        lazy[node] = 0;
    }
    void update(int a, int b, LL val, int node = 1, int l = 0, int r = MAX - 1)
    {
        propagate(node, l, r);
        if(b < l || r < a) return;
        if(a <= l && r <= b)
            lazy[node] += val, propagate(node, l, r);
        else
        {
            update(a, b, val, 2 * node, l, (l + r) / 2);
            update(a, b, val, 2 * node + 1, (l + r) / 2 + 1, r);
            tree[node] = max(tree[2 * node], tree[2 * node + 1]); // (*)
        }
    }
    PLL query(int a, int b, int node = 1, int l = 0, int r = MAX - 1)
    {
        propagate(node, l, r);
        if(b < l || r < a) return {-INF, 0}; // (*)
        if(a <= l && r <= b) return tree[node];
        return max(query(a, b, 2 * node, l, (l + r) / 2), query(a, b, 2 * node + 1, (l + r) / 2 + 1, r)); // (*)
    }
};

const LL INF = 1e18 + 7;

const int N = 1 << 18;

int n, T[N], tmp[N], prz, whe[N];
vector < int > lp, rp;
vector < int > G[N];
int A[N], sz[N], root;

PII treem[2 * N];

PII query_min(int a, int b)
{
    a += N, b += N;
    PII res = min(treem[a], treem[b]);
    while(a / 2 != b / 2)
    {
        if(a % 2 == 0) res = min(res, treem[a + 1]);
        if(b % 2 == 1) res = min(res, treem[b - 1]);
        a /= 2, b /= 2;
    }
    return res;
}

int build(int a, int b)
{
    if(a >= b) return a;
    PII p = query_min(a, b);
    if(a < p.second)
    {
        PII l = query_min(a, p.second - 1);
        G[p.second].push_back(l.second);
        build(a, p.second - 1);
    }
    if(p.second < b)
    {
        PII r = query_min(p.second + 1, b);
        G[p.second].push_back(r.second);
        build(p.second + 1, b);
    }
    return p.second;
}

int cntt = 1;

int dfs(int v)
{
    A[cntt++] = v;
    for(auto u: G[v])
        sz[v] += dfs(u);

    return ++sz[v];
}

SegmentTree treel, treer;

int main()
{
    _upgrade

    cin >> n;
    for(int i = 1; i <= n; i++)
        cin >> T[i];

    if(n == 1)
    {
        cout << "1 0\n";
        return 0;
    }

    for(int i = 1; i <= n; i++)
    {
        if(T[i] == 1)
        {
            prz = i;
            int cnt = 1;
            for(int j = i + 1; j <= n; j++)
                tmp[cnt++] = T[j];
            for(int j = 1; j <= i; j++)
                tmp[cnt++] = T[j];
            for(int j = 1; j <= n; j++)
                T[j] = tmp[j];
            break;
        }
    }

    for(int i = 1; i < n; i++)
        treem[i + N] = {T[i], i};
    for(int i = N - 1; i; i--)
        treem[i] = min(treem[2 * i], treem[2 * i + 1]);

    build(1, n - 1);
    for(int i = 1; i < n; i++)
    {
        whe[T[i]] = i;
    }
    root = whe[2];
    dfs(root);

    for(int i = 1; i < n; i++)
    {
        treer.update(i, i, -INF);
        treel.update(i, i + sz[i] - 1, 1);
    }

    int dep = max(treel.query(1, n - 1).first, treer.query(1, n - 1).first), bestp = 0;

    for(int p = 1; p < n; p++)
    {
        int x = whe[T[p]];
        treel.update(x, x, -INF);
        treel.update(x, x + sz[x] - 1, -1);

        treer.update(x, x, INF);
        treer.update(x, x + sz[x] - 1, 1);

        int tdep = max(treel.query(1, n - 1).first, treer.query(1, n - 1).first);
        if(tdep < dep)
        {
            dep = tdep;
            bestp = p;
        }
    }

    cout << dep + 1 << " " << (bestp + prz) % n << "\n";

	return 0;
}


#include <bits/stdc++.h>

#define pb push_back
#define f first
#define s second

using namespace std;

int main()
{
	int n,aa,sol=0;
	scanf("%i",&n);
	deque<int> a(n);
	vector<int> koliko(n+1),solL(n+1),solR(n+1);
	for(int i=0;i<n;i++)
        scanf("%i",&a[i]),a[i]=n-a[i]+1,koliko[a[i]]=i;
    while(a[0]!=n)
        aa=a[0],a.pop_front(),a.pb(aa);
    a.pb(n);
    vector<pair<int,int> > stk;
    for(int i=1;i<n;i++)
    {
        int mxLevo=0;
        while(stk.size()&&stk.back().f<a[i])
            mxLevo=max(mxLevo+1,stk.back().s+1),stk.pop_back();
        stk.pb({a[i],mxLevo});
        sol=max(sol,(int)stk.size()+mxLevo+1);
        solL[i]=sol;
    }
    sol=0;
    stk.clear();
    for(int i=n-1;i>0;i--)
    {
        int mxLevo=0;
        while(stk.size()&&stk.back().f<a[i])
            mxLevo=max(mxLevo+1,stk.back().s+1),stk.pop_back();
        stk.pb({a[i],mxLevo});
        sol=max(sol,(int)stk.size()+mxLevo+1);
        solR[i]=sol;
    }
    int best=INT_MAX,gde=0;
    for(int i=0;i<n;i++)
        if(1+max(solL[i],solR[i+1])<best)
            best=1+max(solL[i],solR[i+1]),gde=a[i+1];
    printf("%i %i\n",best,koliko[gde]);
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>

#define ll long long
#define pb push_back
#define sz(x) (int)(x).size()
#define mp make_pair
#define f first
#define s second
#define all(x) x.begin(), x.end()
#define D(x) cerr << #x << " is " << (x) << "\n";

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>; ///find_by_order(),order_of_key()
template<class T1, class T2> ostream& operator<<(ostream& os, const pair<T1,T2>& a) { os << '{' << a.f << ", " << a.s << '}'; return os; }
template<class T> ostream& operator<<(ostream& os, const vector<T>& a){os << '{';for(int i=0;i<sz(a);i++){if(i>0&&i<sz(a))os << ", ";os << a[i];}os<<'}';return os;}
template<class T> ostream& operator<<(ostream& os, const set<T>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T> ostream& operator<<(ostream& os, const multiset<T>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}
template<class T1,class T2> ostream& operator<<(ostream& os, const map<T1,T2>& a) {os << '{';int i=0;for(auto p:a){if(i>0&&i<sz(a))os << ", ";os << p;i++;}os << '}';return os;}

struct ver{
    int val,l,up;
};
int main()
{
	int n,cnt=0,aa;
	scanf("%i",&n);
	if(n==1)
    {
        printf("1 0\n");
        return 0;
    }
	deque<int> a(n);
	vector<int> koliko(n+1);
	for(int i=0;i<n;i++)
        scanf("%i",&a[i]),a[i]=n-a[i]+1,koliko[a[i]]=i;
    while(a[0]!=n)
        aa=a[0],a.pop_front(),a.pb(aa),cnt++;
    a.pb(n);
    int sol=0;
    vector<ver> stk;
    vector<int> solL(n+1),solR(n+1);
    for(int i=1;i<n;i++)
    {
        int mxLevo=0;
        while(stk.size()&&stk.back().val<a[i])
            mxLevo=max(mxLevo+1,stk.back().l+1),stk.pop_back();
        ver tr={a[i],mxLevo,stk.size()};
        stk.pb(tr);
        sol=max(sol,tr.l+tr.up+1);
        solL[i]=sol;
    }
    sol=0;
    stk.clear();
    for(int i=n-1;i>0;i--)
    {
        int mxLevo=0;
        while(stk.size()&&stk.back().val<a[i])
            mxLevo=max(mxLevo+1,stk.back().l+1),stk.pop_back();
        ver tr={a[i],mxLevo,stk.size()};
        stk.pb(tr);
        sol=max(sol,tr.l+tr.up+1);
        solR[i]=sol;
    }
    int best=INT_MAX,gde;
    for(int i=0;i<n;i++)
    {
        int trsol=1+max(solL[i],solR[i+1]);
        if(trsol<best)
            best=trsol,gde=a[i+1];
    }
    printf("%i %i\n",best,koliko[gde]);
    return 0;
}
/*
7
7 2 4 1 5 6 3
*/


#include <bits/stdc++.h>

#define pb push_back
#define f first
#define s second

using namespace std;

int main()
{
	int n,aa,sol=0;
	scanf("%i",&n);
	deque<int> a(n);
	vector<int> koliko(n+1),solL(n+1),solR(n+1);
	for(int i=0;i<n;i++)
        scanf("%i",&a[i]),a[i]=n-a[i]+1,koliko[a[i]]=i;
    while(a[0]!=n)
        aa=a[0],a.pop_front(),a.pb(aa);
    a.pb(n);
    vector<pair<int,int> > stk;
    for(int i=1;i<n;i++)
    {
        int mxLevo=0;
        while(stk.size()&&stk.back().f<a[i])
            mxLevo=max(mxLevo+1,stk.back().s+1),stk.pop_back();
        sol=max(sol,(int)stk.size()+mxLevo+1);
        stk.pb({a[i],mxLevo});
        solL[i]=sol;
    }
    sol=0;
    stk.clear();
    for(int i=n-1;i>0;i--)
    {
        int mxLevo=0;
        while(stk.size()&&stk.back().f<a[i])
            mxLevo=max(mxLevo+1,stk.back().s+1),stk.pop_back();
        sol=max(sol,(int)stk.size()+mxLevo+1);
        stk.pb({a[i],mxLevo});
        solR[i]=sol;
    }
    int best=INT_MAX,gde=0;
    for(int i=0;i<n;i++)
        if(1+max(solL[i],solR[i+1])<best)
            best=1+max(solL[i],solR[i+1]),gde=a[i+1];
    printf("%i %i\n",best,koliko[gde]);
    return 0;
}


#include <bits/stdc++.h>

#define pb push_back
#define f first
#define s second

using namespace std;

int sol,n,aa,best=INT_MAX,gde;
vector<pair<int,int> > stk;
void dodaj(int a)
{
    int mxLevo=0;
    while(stk.size()&&stk.back().f<a)
        mxLevo=max(mxLevo+1,stk.back().s+1),stk.pop_back();
    sol=max(sol,(int)stk.size()+mxLevo+1);
    stk.pb({a,mxLevo});
}
int main()
{
	scanf("%i",&n);
	deque<int> a(n);
	vector<int> koliko(n+1),solL(n+1),solR(n+1);
	for(int i=0;i<n;i++)
        scanf("%i",&a[i]),a[i]=n-a[i]+1,koliko[a[i]]=i;
    while(a[0]!=n)
        aa=a[0],a.pop_front(),a.pb(aa);
    a.pb(n);
    for(int i=1;i<n;i++)
        dodaj(a[i]),solL[i]=sol;
    sol=0;
    stk.clear();
    for(int i=n-1;i>0;i--)
        dodaj(a[i]),solR[i]=sol;
    for(int i=0;i<n;i++)
        if(1+max(solL[i],solR[i+1])<best)
            best=1+max(solL[i],solR[i+1]),gde=a[i+1];
    printf("%i %i\n",best,koliko[gde]);
    return 0;
}


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

#define FAST ios_base::sync_with_stdio(false); cin.tie(0);
#define pb push_back
#define eb emplace_back
#define ins insert
#define ph push
#define f first
#define s second
#define cbr cerr << "hi\n"
#define mmst(x, v) memset((x), v, sizeof ((x)))
#define siz(x) ll(x.size())
#define all(x) (x).begin(), (x).end()
#define lbd(x, y) lower_bound(all(x), y)
#define ubd(x, y) upper_bound(all(x), y)
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());    //can be used by calling rng() or shuffle(A, A+n, rng)
inline long long rand(long long x, long long y) { return (rng() % (y+1-x)) + x; } //inclusivesss
string inline to_string(char c) {string s(1,c);return s;} template<typename T> inline T gcd(T a,T b){ return a==0?llabs(b):gcd(b%a,a); }

typedef long long ll;
typedef long double ld;
#define FOR(i, s, e) for(ll i=s;i<=ll(e);++i)
#define DEC(i, s, e) for(ll i=s;i>=ll(e);--i)
typedef pair<ll,ll>pi; typedef pair<ll,pi>spi; typedef pair<pi,pi>dpi;

#define LLINF ((long long) 1e18)//1234567890987654321
#define INF 1234567890ll
#define cerr if(0)cout
#define MAXN (200006)
ll n;
pi A[MAXN*2];
stack<ll> stk;
struct node {
	int s,e,m;
	ll v, o, add;
	node *l,*r;
	node(int _S,int _E) {
		s=_S,e=_E,m=(s+e)>>1;
		v=0;o=0;add=0;
		if(s^e) {
			l=new node(s,m);
			r=new node(m+1,e);
			v=min(l->v,r->v);
		} else v=A[s].f;
	}
	int findleft(int x,int y,ll nval) {
		if(x>y) return x;
		if(s==x&&e==y) {
			if(A[e].f < nval) return y+1;
			if(s==e) return s;
			if(r->v >= nval) return l->findleft(x,m,nval);
			else return r->findleft(m+1,y,nval);
		} else {
			if(x>m) return r->findleft(x,y,nval);
			else if(y<=m) return l->findleft(x,y,nval);
			else {
				ll rv = r->findleft(m+1, y, nval);
				if(rv == m+1) return l->findleft(x, m, nval);
				else return rv;
			}
		}
	}
	int findright(int x,int y,ll nval) {
		if(x>y) return y;
		if(s==x&&e==y) {
			if(A[s].f < nval) return x-1;
			if(s==e) return s;
			if(l->v >= nval) return r->findright(m+1,y,nval);
			else return l->findright(x,m,nval);
		} else {
			if(x>m) return r->findright(x,y,nval);
			else if(y<=m) return l->findright(x,y,nval);
			else {
				ll lv=l->findright(x, m, nval);
				if(lv == m) return r->findright(m+1, y, nval);
				else return lv;
			}
		}
	}
	void update(int x,int y,ll nval) {
		value();
		if(s==x&&e==y) { add+=nval; return; }
		if(x>m) r->update(x,y,nval);
		else if(y<=m) l->update(x,y,nval);
		else l->update(x,m,nval), r->update(m+1,y,nval);
		o=max(l->value(),r->value());
	}
	ll value() {
		o+=add;
		if(s^e){
			l->add+=add;
			r->add+=add;
		}
		add=0;
		return o;
	}
	ll rmq(int x,int y) { value();
		if(s==x&&e==y) return o;
		if(x>m) return r->rmq(x,y);
		else if(y<=m) return l->rmq(x,y);
		else return max(l->rmq(x,m),r->rmq(m+1,y));
	}
	void set(int x,ll nval) {
		value();
		if(s==e) {
			o=nval;
			return;
		}
		if(x>m) r->set(x,nval); else l->set(x,nval);
		o=max(l->value(), r->value());
	}
	void output(int x,int y) {
		value();
		if(s==x&&e==y) {
			if(s==e) {
				cout<<o<<' ';
				return;
			}
			l->output(s,m);
			r->output(m+1,e);
		} else l->output(x,y);
	}
} *seg;
deque<pi> dq;
int main()
{
	FAST
	cin>>n;
	FOR(i,n,2*n-1) cin>>A[i].f, A[i].s=i-n, A[i-n]=A[i];
	seg=new node(0, 2*n-1);
	auto update=[&](int x,int y,int op=1) {
		if(x>y) return;
		x=A[x].s, y=A[y].s;
		if(x>y) seg->update(x,n-1,op), seg->update(0, y, op);
		else seg->update(x, y, op);
	};
	auto check=[&](deque<pi> dq) {
		ll p = LLINF;
		for(auto i:dq) { assert(p > i.f), p = i.f; }
		return;
	};
	auto proc=[&](int x) {
		ll e = x-1;
		ll s=e-n+1;
		assert(A[s].f==A[x].f);
		if(dq.size() && dq.back().f == A[x].f) dq.pop_back();
		while(dq.size() && dq[0].f > A[x].f) dq.pop_front();
		seg->set(A[x].s, dq.size());
		dq.push_front(pi(A[x].f, s)); // check(dq);
		for(auto i:dq) cerr<<i.f<<' '; cerr<<'\n';
		ll rb=seg->findright(s+1, e, A[s].f);
		update(s+1, rb);
		ll lb=seg->findleft(s+1, e, A[s].f);
		update(lb, e, -1);
	};
	FOR(i,n,2*n-1) {
		ll lb=seg->findleft(n,i-1,A[i].f);
		update(lb,i-1);
		ll rb=seg->findright(i+1,2*n-1,A[i].f);
		update(i+1,rb);
		if(i==n || lb == n) {
			dq.eb(A[i].f, i);
		}
	}
	ll co = 0;
	pi ans=pi(seg->rmq(0, n-1), co);
	ll s = n, e = 2*n-1;
	cerr<<co<<":\n";
	// seg->output(0, n-1);
	cerr<<"\n\n";
	while(1) {
		-- s, -- e; ++ co;
		if(s == 0 && e == n-1) break;
		proc(e+1);
		ans=min(ans, pi(seg->rmq(0, n-1), co));
		cerr<<co<<":\n";
		// seg->output(0, n-1);
		cerr<<"\n\n";
		assert(seg->rmq(n, 2*n-1) == 0);
	}
	cout<<ans.f+1<<' '<<(n-ans.s)%n<<'\n';
}


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

#define FAST ios_base::sync_with_stdio(false); cin.tie(0);
#define pb push_back
#define eb emplace_back
#define ins insert
#define ph push
#define f first
#define s second
#define cbr cerr << "hi\n"
#define mmst(x, v) memset((x), v, sizeof ((x)))
#define siz(x) ll(x.size())
#define all(x) (x).begin(), (x).end()
#define lbd(x, y) lower_bound(all(x), y)
#define ubd(x, y) upper_bound(all(x), y)
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());    //can be used by calling rng() or shuffle(A, A+n, rng)
inline long long rand(long long x, long long y) { return (rng() % (y+1-x)) + x; } //inclusivesss
string inline to_string(char c) {string s(1,c);return s;} template<typename T> inline T gcd(T a,T b){ return a==0?llabs(b):gcd(b%a,a); }

typedef long long ll;
typedef long double ld;
#define FOR(i, s, e) for(ll i=s;i<=ll(e);++i)
#define DEC(i, s, e) for(ll i=s;i>=ll(e);--i)
typedef pair<ll,ll>pi; typedef pair<ll,pi>spi; typedef pair<pi,pi>dpi;

#define LLINF ((long long) 1e18)//1234567890987654321
#define INF 1234567890ll
// #define cerr if(0)cout
#define MAXN (200006)
ll n;
pi A[MAXN*2];
stack<ll> stk;
struct node {
	int s,e,m;
	ll v, o, add;
	node *l,*r;
	node(int _S,int _E) {
		s=_S,e=_E,m=(s+e)>>1;
		v=0;o=0;add=0;
		if(s^e) {
			l=new node(s,m);
			r=new node(m+1,e);
			v=min(l->v,r->v);
		} else v=A[s].f;
	}
	int findleft(int x,int y,ll nval) {
		if(x>y) return x;
		if(s==x&&e==y) {
			if(A[e].f < nval) return y+1;
			if(s==e) return s;
			if(r->v >= nval) return l->findleft(x,m,nval);
			else return r->findleft(m+1,y,nval);
		} else {
			if(x>m) return r->findleft(x,y,nval);
			else if(y<=m) return l->findleft(x,y,nval);
			else {
				ll rv = r->findleft(m+1, y, nval);
				if(rv == m+1) return l->findleft(x, m, nval);
				else return rv;
			}
		}
	}
	int findright(int x,int y,ll nval) {
		if(x>y) return y;
		if(s==x&&e==y) {
			if(A[s].f < nval) return x-1;
			if(s==e) return s;
			if(l->v >= nval) return r->findright(m+1,y,nval);
			else return l->findright(x,m,nval);
		} else {
			if(x>m) return r->findright(x,y,nval);
			else if(y<=m) return l->findright(x,y,nval);
			else {
				ll lv=l->findright(x, m, nval);
				if(lv == m) return r->findright(m+1, y, nval);
				else return lv;
			}
		}
	}
	void update(int x,int y,ll nval) {
		if(s==x&&e==y) { add+=nval; return; }
		if(x>m) r->update(x,y,nval);
		else if(y<=m) l->update(x,y,nval);
		else l->update(x,m,nval), r->update(m+1,y,nval);
		o=max(l->value(),r->value());
	}
	ll value() {
		o+=add;
		if(s^e){
			l->add+=add;
			r->add+=add;
		}
		add=0;
		return o;
	}
	ll rmq(int x,int y) { value();
		if(s==x&&e==y) return o;
		if(x>m) return r->rmq(x,y);
		else if(y<=m) return l->rmq(x,y);
		else return max(l->rmq(x,m),r->rmq(m+1,y));
	}
	void set(int x,ll nval) {
		value();
		if(s==e) {
			o=nval;
			return;
		}
		if(x>m) r->set(x,nval); else l->set(x,nval);
		o=max(l->o, r->o);
	}
	void output(int x,int y) {
		value();
		if(s==x&&e==y) {
			if(s==e) {
				cout<<o<<' ';
				return;
			}
			l->output(s,m);
			r->output(m+1,e);
		} else l->output(x,y);
	}
} *seg;
deque<pi> dq;
int main()
{
	FAST
	cin>>n;
	FOR(i,n,2*n-1) cin>>A[i].f, A[i].s=i-n, A[i-n]=A[i];
	seg=new node(0, 2*n-1);
	auto update=[&](int x,int y,int op=1) {
		if(x>y) return;
		x=A[x].s, y=A[y].s;
		if(x>y) seg->update(x,n-1,op), seg->update(0, y, op);
		else seg->update(x, y, op);
	};
	auto check=[&](deque<pi> dq) {
		ll p = LLINF;
		for(auto i:dq) { assert(p > i.f), p = i.f; }
		return;
	};
	auto proc=[&](int x) {
		ll e = x-1;
		ll s=e-n+1;
		assert(A[s].f==A[x].f);
		if(dq.size() && dq.back().s == x) dq.pop_back();
		while(dq.size() && dq[0].f > A[x].f) dq.pop_front();
		seg->set(A[x].s, dq.size());
		dq.push_front(pi(A[x].f, s)); check(dq);
		ll rb=seg->findright(s+1, e, A[s].f);
		update(s+1, rb);
		ll lb=seg->findleft(s+1, e, A[s].f);
		update(lb, e, -1);
	};
	FOR(i,n,2*n-1) {
		ll lb=seg->findleft(n,i-1,A[i].f);
		update(lb,i-1);
		ll rb=seg->findright(i+1,2*n-1,A[i].f);
		update(i+1,rb);
		if(i==n || lb == n) {
			dq.eb(A[i].f, i);
		}
	}
	ll co = 0;
	pi ans=pi(seg->rmq(0, n-1), co);
	ll s = n, e = 2*n-1;
	while(1) {
		-- s, -- e; ++ co;
		if(s == 0 && e == n-1) break;
		proc(e+1);
		ans=min(ans, pi(seg->rmq(0, n-1), co));
	}
	cout<<ans.f+1<<' '<<(n-ans.s)%n<<'\n';
}


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

#define FAST ios_base::sync_with_stdio(false); cin.tie(0);
#define pb push_back
#define eb emplace_back
#define ins insert
#define ph push
#define f first
#define s second
#define cbr cerr << "hi\n"
#define mmst(x, v) memset((x), v, sizeof ((x)))
#define siz(x) ll(x.size())
#define all(x) (x).begin(), (x).end()
#define lbd(x, y) lower_bound(all(x), y)
#define ubd(x, y) upper_bound(all(x), y)
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());    //can be used by calling rng() or shuffle(A, A+n, rng)
inline long long rand(long long x, long long y) { return (rng() % (y+1-x)) + x; } //inclusivesss
string inline to_string(char c) {string s(1,c);return s;} template<typename T> inline T gcd(T a,T b){ return a==0?llabs(b):gcd(b%a,a); }

typedef long long ll;
typedef long double ld;
#define FOR(i, s, e) for(ll i=s;i<=ll(e);++i)
#define DEC(i, s, e) for(ll i=s;i>=ll(e);--i)
typedef pair<ll,ll>pi; typedef pair<ll,pi>spi; typedef pair<pi,pi>dpi;

#define LLINF ((long long) 1e18)//1234567890987654321
#define INF 1234567890ll
// #define cerr if(0)cout
#define MAXN (200006)
ll n;
pi A[MAXN*2];
stack<ll> stk;
struct node {
	int s,e,m;
	ll v, o, add;
	node *l,*r;
	node(int _S,int _E) {
		s=_S,e=_E,m=(s+e)>>1;
		v=0;o=0;add=0;
		if(s^e) {
			l=new node(s,m);
			r=new node(m+1,e);
			v=min(l->v,r->v);
		} else v=A[s].f;
	}
	int findleft(int x,int y,ll nval) {
		if(x>y) return x;
		if(s==x&&e==y) {
			if(A[e].f < nval) return y+1;
			if(s==e) return s;
			if(r->v >= nval) return l->findleft(x,m,nval);
			else return r->findleft(m+1,y,nval);
		} else {
			if(x>m) return r->findleft(x,y,nval);
			else if(y<=m) return l->findleft(x,y,nval);
			else {
				ll lv = l->findleft(x,m,nval);
				if(lv <= m) return lv;
				else return r->findleft(m+1,y,nval);
			}
		}
	}
	int findright(int x,int y,ll nval) {
		if(x>y) return y;
		if(s==x&&e==y) {
			if(A[s].f < nval) return x-1;
			if(s==e) return s;
			if(l->v >= nval) return r->findright(m+1,y,nval);
			else return l->findright(x,m,nval);
		} else {
			if(x>m) return r->findright(x,y,nval);
			else if(y<=m) return l->findright(x,y,nval);
			else {
				ll rv=r->findright(m+1,y,nval);
				if(rv <= m) return l->findright(x,m,nval);
				else return rv;
			}
		}
	}
	void update(int x,int y,ll nval) {
		if(s==x&&e==y) { add+=nval; return; }
		if(x>m) r->update(x,y,nval);
		else if(y<=m) l->update(x,y,nval);
		else l->update(x,m,nval), r->update(m+1,y,nval);
		o=max(l->value(),r->value());
	}
	ll value() {
		o+=add;
		if(s^e){
			l->add+=add;
			r->add+=add;
		}
		add=0;
		return o;
	}
	ll rmq(int x,int y) { value();
		if(s==x&&e==y) return o;
		if(x>m) return r->rmq(x,y);
		else if(y<=m) return l->rmq(x,y);
		else return max(l->rmq(x,m),r->rmq(m+1,y));
	}
	void set(int x,ll nval) {
		value();
		if(s==e) {
			o=nval;
			return;
		}
		if(x>m) r->set(x,nval); else l->set(x,nval);
		o=max(l->o, r->o);
	}
	void output(int x,int y) {
		value();
		if(s==x&&e==y) {
			if(s==e) {
				cout<<o<<' ';
				return;
			}
			l->output(s,m);
			r->output(m+1,e);
		} else l->output(x,y);
	}
} *seg;
deque<pi> dq;
int main()
{
	FAST
	cin>>n;
	FOR(i,n,2*n-1) cin>>A[i].f, A[i].s=i-n, A[i-n]=A[i];
	seg=new node(0, 2*n-1);
	auto update=[&](int x,int y) {
		if(x>y) return;
		x=A[x].s, y=A[y].s;
		if(x>y) seg->update(x,n-1,1), seg->update(0, y, 1);
		else seg->update(x, y, 1);
	};
	auto proc=[&](int x) {
		ll e = x-1;
		ll s=e-n+1;
		assert(A[s].f==A[x].f);
		seg->set(A[x].s, 0);
		if(dq.size() && dq.back().s == x) dq.pop_back();
		while(dq.size() && dq[0].f > A[x].f) dq.pop_front();
		seg->set(A[x].s, dq.size());
		dq.push_front(pi(A[x].f, s));
		ll rb=seg->findright(s+1, e, A[s].f);
		update(s+1, rb);
	};
	FOR(i,n,2*n-1) {
		ll lb=seg->findleft(n,i-1,A[i].f);
		update(lb,i-1);
		ll rb=seg->findright(i+1,2*n-1,A[i].f);
		update(i+1,rb);
		if(i==n || lb == n) {
			dq.eb(A[i].f, i);
		}
	}
	ll co = 0;
	pi ans=pi(seg->rmq(0, n-1), co);
	ll s = n, e = 2*n-1;
	while(1) {
		-- s, -- e; ++ co;
		if(s == 0 && e == n-1) break;
		proc(e+1);
		ans=min(ans, pi(seg->rmq(0, n-1), co));
	}
	cout<<ans.f+1<<' '<<n-ans.s<<'\n';
}


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

#define FAST ios_base::sync_with_stdio(false); cin.tie(0);
#define pb push_back
#define eb emplace_back
#define ins insert
#define ph push
#define f first
#define s second
#define cbr cerr << "hi\n"
#define mmst(x, v) memset((x), v, sizeof ((x)))
#define siz(x) ll(x.size())
#define all(x) (x).begin(), (x).end()
#define lbd(x, y) lower_bound(all(x), y)
#define ubd(x, y) upper_bound(all(x), y)
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());    //can be used by calling rng() or shuffle(A, A+n, rng)
inline long long rand(long long x, long long y) { return (rng() % (y+1-x)) + x; } //inclusivesss
string inline to_string(char c) {string s(1,c);return s;} template<typename T> inline T gcd(T a,T b){ return a==0?llabs(b):gcd(b%a,a); }

typedef long long ll;
typedef long double ld;
#define FOR(i, s, e) for(ll i=s;i<=ll(e);++i)
#define DEC(i, s, e) for(ll i=s;i>=ll(e);--i)
typedef pair<ll,ll>pi; typedef pair<ll,pi>spi; typedef pair<pi,pi>dpi;

#define LLINF ((long long) 1e18)//1234567890987654321
#define INF 1234567890ll
#define cerr if(0)cout
#define MAXN (200006)
ll n;
pi A[MAXN*2];
stack<ll> stk;
struct node {
	int s,e,m;
	ll v, o, add;
	node *l,*r;
	node(int _S,int _E) {
		s=_S,e=_E,m=(s+e)>>1;
		v=0;o=0;add=0;
		if(s^e) {
			l=new node(s,m);
			r=new node(m+1,e);
			v=min(l->v,r->v);
		} else v=A[s].f;
	}
	int findleft(int x,int y,ll nval) {
		if(x>y) return x;
		ll mx = LLINF, pos = y+1;
		DEC(i,y,x) {
			mx=min(mx, A[i].f);
			if(mx >= nval) pos=min(pos, i);
		}
		return pos;
		if(s==x&&e==y) {
			if(A[e].f < nval) return y+1;
			if(s==e) return s;
			if(r->v >= nval) return l->findleft(x,m,nval);
			else return r->findleft(m+1,y,nval);
		} else {
			if(x>m) return r->findleft(x,y,nval);
			else if(y<=m) return l->findleft(x,y,nval);
			else {
				ll rv = r->findleft(m+1, y, nval);
				if(rv == m+1) return l->findleft(x, m, nval);
				else return rv;
			}
		}
	}
	int findright(int x,int y,ll nval) {
		if(x>y) return y;
		ll mx = LLINF, pos = x-1;
		FOR(i,x,y) {
			mx=min(mx, A[i].f);
			if(mx >= nval) pos=max(pos, i);
		}
		return pos;
		if(s==x&&e==y) {
			if(A[s].f < nval) return x-1;
			if(s==e) return s;
			if(l->v >= nval) return r->findright(m+1,y,nval);
			else return l->findright(x,m,nval);
		} else {
			if(x>m) return r->findright(x,y,nval);
			else if(y<=m) return l->findright(x,y,nval);
			else {
				ll lv=l->findright(x, m, nval);
				if(lv == m) return r->findright(m+1, y, nval);
				else return lv;
			}
		}
	}
	void update(int x,int y,ll nval) {
		value();
		if(s==x&&e==y) { add+=nval; return; }
		if(x>m) r->update(x,y,nval);
		else if(y<=m) l->update(x,y,nval);
		else l->update(x,m,nval), r->update(m+1,y,nval);
		o=max(l->value(),r->value());
	}
	ll value() {
		o+=add;
		if(s^e){
			l->add+=add;
			r->add+=add;
		}
		add=0;
		return o;
	}
	ll rmq(int x,int y) { value();
		if(s==x&&e==y) return o;
		if(x>m) return r->rmq(x,y);
		else if(y<=m) return l->rmq(x,y);
		else return max(l->rmq(x,m),r->rmq(m+1,y));
	}
	void set(int x,ll nval) {
		value();
		if(s==e) {
			o=nval;
			return;
		}
		if(x>m) r->set(x,nval); else l->set(x,nval);
		o=max(l->o, r->o);
	}
	void output(int x,int y) {
		value();
		if(s==x&&e==y) {
			if(s==e) {
				cout<<o<<' ';
				return;
			}
			l->output(s,m);
			r->output(m+1,e);
		} else l->output(x,y);
	}
} *seg;
deque<pi> dq;
int main()
{
	FAST
	cin>>n;
	FOR(i,n,2*n-1) cin>>A[i].f, A[i].s=i-n, A[i-n]=A[i];
	seg=new node(0, 2*n-1);
	auto update=[&](int x,int y,int op=1) {
		if(x>y) return;
		x=A[x].s, y=A[y].s;
		if(x>y) seg->update(x,n-1,op), seg->update(0, y, op);
		else seg->update(x, y, op);
	};
	auto check=[&](deque<pi> dq) {
		ll p = LLINF;
		for(auto i:dq) { assert(p > i.f), p = i.f; }
		return;
	};
	auto proc=[&](int x) {
		ll e = x-1;
		ll s=e-n+1;
		assert(A[s].f==A[x].f);
		if(dq.size() && dq.back().f == A[x].f) dq.pop_back();
		while(dq.size() && dq[0].f > A[x].f) dq.pop_front();
		seg->set(A[x].s, dq.size());
		dq.push_front(pi(A[x].f, s)); check(dq);
		for(auto i:dq) cerr<<i.f<<' '; cerr<<'\n';
		ll rb=seg->findright(s+1, e, A[s].f);
		update(s+1, rb);
		ll lb=seg->findleft(s+1, e, A[s].f);
		update(lb, e, -1);
	};
	FOR(i,n,2*n-1) {
		ll lb=seg->findleft(n,i-1,A[i].f);
		update(lb,i-1);
		ll rb=seg->findright(i+1,2*n-1,A[i].f);
		update(i+1,rb);
		if(i==n || lb == n) {
			dq.eb(A[i].f, i);
		}
	}
	ll co = 0;
	pi ans=pi(seg->rmq(0, n-1), co);
	ll s = n, e = 2*n-1;
	cerr<<co<<":\n";
	// seg->output(0, n-1);
	cerr<<"\n\n";
	while(1) {
		-- s, -- e; ++ co;
		if(s == 0 && e == n-1) break;
		proc(e+1);
		ans=min(ans, pi(seg->rmq(0, n-1), co));
		cerr<<co<<":\n";
		// seg->output(0, n-1);
		cerr<<"\n\n";
		assert(seg->rmq(n, 2*n-1) == 0);
	}
	cout<<ans.f+1<<' '<<(n-ans.s)%n<<'\n';
}


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

#define FAST ios_base::sync_with_stdio(false); cin.tie(0);
#define pb push_back
#define eb emplace_back
#define ins insert
#define ph push
#define f first
#define s second
#define cbr cerr << "hi\n"
#define mmst(x, v) memset((x), v, sizeof ((x)))
#define siz(x) ll(x.size())
#define all(x) (x).begin(), (x).end()
#define lbd(x, y) lower_bound(all(x), y)
#define ubd(x, y) upper_bound(all(x), y)
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());    //can be used by calling rng() or shuffle(A, A+n, rng)
inline long long rand(long long x, long long y) { return (rng() % (y+1-x)) + x; } //inclusivesss
string inline to_string(char c) {string s(1,c);return s;} template<typename T> inline T gcd(T a,T b){ return a==0?llabs(b):gcd(b%a,a); }

typedef long long ll;
typedef long double ld;
#define FOR(i, s, e) for(ll i=s;i<=ll(e);++i)
#define DEC(i, s, e) for(ll i=s;i>=ll(e);--i)
typedef pair<ll,ll>pi; typedef pair<ll,pi>spi; typedef pair<pi,pi>dpi;

#define LLINF ((long long) 1e18)//1234567890987654321
#define INF 1234567890ll
// #define cerr if(0)cout
#define MAXN (200006)
ll n;
pi A[MAXN*2];
stack<ll> stk;
struct node {
	int s,e,m;
	ll v, o, add;
	node *l,*r;
	node(int _S,int _E) {
		s=_S,e=_E,m=(s+e)>>1;
		v=0;o=0;
		if(s^e) {
			l=new node(s,m);
			r=new node(m+1,e);
			v=min(l->v,r->v);
		} else v=A[s].f;
	}
	int findleft(int x,int y,ll nval) {
		if(x>y) return x;
		if(s==x&&e==y) {
			if(A[e].f < nval) return y+1;
			if(s==e) return s;
			if(r->v >= nval) return l->findleft(x,m,nval);
			else return r->findleft(m+1,y,nval);
		} else {
			if(x>m) return r->findleft(x,y,nval);
			else if(y<=m) return l->findleft(x,y,nval);
			else {
				ll lv = l->findleft(x,m,nval);
				if(lv <= m) return lv;
				else return r->findleft(m+1,y,nval);
			}
		}
	}
	int findright(int x,int y,ll nval) {
		if(x>y) return y;
		if(s==x&&e==y) {
			if(A[s].f < nval) return x-1;
			if(s==e) return s;
			if(l->v >= nval) return r->findright(m+1,y,nval);
			else return l->findright(x,m,nval);
		} else {
			if(x>m) return r->findright(x,y,nval);
			else if(y<=m) return l->findright(x,y,nval);
			else {
				ll rv=r->findright(m+1,y,nval);
				if(rv <= m) return l->findright(x,m,nval);
				else return rv;
			}
		}
	}
	void update(int x,int y,ll nval) {
		if(s==x&&e==y) { add+=nval; return; }
		if(x>m) r->update(x,y,nval);
		else if(y<=m) l->update(x,y,nval);
		else l->update(x,m,nval), r->update(m+1,y,nval);
		o=max(l->value(),r->value());
	}
	ll value() {
		o+=add;
		if(s^e){
			l->add+=add;
			r->add+=add;
		}
		add=0;
		return o;
	}
	ll rmq(int x,int y) { value();
		if(s==x&&e==y) return o;
		if(x>m) return r->rmq(x,y);
		else if(y<=m) return l->rmq(x,y);
		else return max(l->rmq(x,m),r->rmq(m+1,y));
	}
	void set(int x,ll nval) {
		value();
		if(s==e) {
			o=nval;
			return;
		}
		if(x>m) r->set(x,nval); else l->set(x,nval);
		o=max(l->o, r->o);
	}
	void output(int x,int y) {
		value();
		if(s==x&&e==y) {
			if(s==e) {
				cout<<o<<' ';
				return;
			}
			l->output(s,m);
			r->output(m+1,e);
		} else l->output(x,y);
	}
} *seg;
deque<pi> dq;
int main()
{
	FAST
	cin>>n;
	FOR(i,n,2*n-1) cin>>A[i].f, A[i].s=i-n, A[i-n]=A[i];
	seg=new node(0, 2*n-1);
	auto update=[&](int x,int y) {
		if(x>y) return;
		x=A[x].s, y=A[y].s;
		if(x>y) seg->update(x,n-1,1), seg->update(0, y, 1);
		else seg->update(x, y, 1);
	};
	auto proc=[&](int x) {
		ll e = x-1;
		ll s=e-n+1;
		assert(A[s].f==A[x].f);
		seg->set(A[x].s, 0);
		if(dq.size() && dq.back().s == x) dq.pop_back();
		while(dq.size() && dq[0].f > A[x].f) dq.pop_front();
		seg->set(A[x].s, dq.size());
		dq.push_front(pi(A[x].f, s));
		ll rb=seg->findright(s+1, e, A[s].f);
		update(s+1, rb);
	};
	FOR(i,n,2*n-1) {
		ll lb=seg->findleft(n,i-1,A[i].f);
		update(lb,i-1);
		ll rb=seg->findright(i+1,2*n-1,A[i].f);
		update(i+1,rb);
		if(i==n || lb == n) {
			dq.eb(A[i].f, i);
		}
	}
	ll co = 0;
	pi ans=pi(seg->rmq(0, n-1), co);
	ll s = n, e = 2*n-1;
	while(1) {
		-- s, -- e; ++ co;
		if(s == 0 && e == n-1) break;
		proc(e+1);
		ans=min(ans, pi(seg->rmq(0, n-1), co));
	}
	cout<<ans.f+1<<' '<<n-ans.s<<'\n';
}


#include <bits/stdc++.h>

using namespace std;

template<class T, class U>
void ckmin(T &a, U b)
{
    if (a > b) a = b;
}

template<class T, class U>
void ckmax(T &a, U b)
{
    if (a < b) a = b;
}

#define MP make_pair
#define PB push_back
#define LB lower_bound
#define UB upper_bound
#define fi first
#define se second
#define SZ(x) ((int) (x).size())
#define ALL(x) (x).begin(), (x).end()
#define FOR(i, a, b) for (auto i = (a); i < (b); i++)
#define FORD(i, a, b) for (auto i = (a) - 1; i >= (b); i--)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<pii> vpi;
typedef vector<pll> vpl;

const int MAXN = 400013;
const int INF = 1000000007;

int N;
int arr[MAXN];
pii ans = {INF, INF};
int lt[MAXN], rt[MAXN];
int stor[20][MAXN];
int depth[MAXN];
int seg[3 * MAXN], lazy[3 * MAXN];
vi vec;

int comb(int i, int j)
{
    if (arr[i] == arr[j]) return i;
    return (arr[i] < arr[j] ? i : j);
}
int qry(int L, int R)
{
    int sz = 31 - __builtin_clz(R - L + 1);
    return comb(stor[sz][L], stor[sz][R - (1 << sz) + 1]);
}
void solve(int L, int R, int d)
{
    if (L > R) return;
    int idx = qry(L, R);
    depth[idx] = d;
    solve(L, idx - 1, d + 1);
    solve(idx + 1, R, d + 1);
}
void build(int w, int L, int R)
{
    lazy[w] = 0;
    if (L == R)
    {
        seg[w] = depth[L];
        return;
    }
    int mid = (L + R) >> 1;
    build(w << 1, L, mid);
    build(w << 1 | 1, mid + 1, R);
    seg[w] = max(seg[w << 1], seg[w << 1 | 1]);
}
void push(int w, int L, int R)
{
    if (lazy[w] == 0) return;
    seg[w] += lazy[w];
    if (L != R)
    {
        lazy[w << 1] += lazy[w];
        lazy[w << 1 | 1] += lazy[w];
    }
    lazy[w] = 0;
    return;
}
void update(int w, int L, int R, int a, int b, int v)
{
    push(w, L, R);
    if (b < L || R < a) return;
    if (a <= L && R <= b)
    {
        lazy[w] += v;
        push(w, L, R);
        return;
    }
    int mid = (L + R) >> 1;
    update(w << 1, L, mid, a, b, v);
    update(w << 1 | 1, mid + 1, R, a, b, v);
    seg[w] = max(seg[w << 1], seg[w << 1 | 1]);
}
int query(int w, int L, int R, int a, int b)
{
    push(w, L, R);
    if (a <= L && R <= b)
    {
        return seg[w];
    }
    int mid = (L + R) >> 1;
    if (b <= mid) return query(w << 1, L, mid, a, b);
    if (mid < a) return query(w << 1 | 1, mid + 1, R, a, b);
    return max(query(w << 1, L, mid, a, b), query(w << 1 | 1, mid + 1, R, a, b));
}

int32_t main()
{
    cout << fixed << setprecision(12);
    cerr << fixed << setprecision(4);
    ios_base::sync_with_stdio(false); cin.tie(0);
    cin >> N;
    FOR(i, 1, N + 1)
    {
        cin >> arr[i];
        arr[i + N] = arr[i];
    }
    FOR(i, 0, 2 * N + 2)
    {
        stor[0][i] = i;
    }
    FOR(i, 1, 20)
    {
        FOR(j, 0, 2 * N + 2 - (1 << i) + 1)
        {
            stor[i][j] = comb(stor[i - 1][j], stor[i - 1][j + (1 << (i - 1))]);
        }
    }
    //initially, you know each nodes depth.
    //then for each i that disappears, it was a record min for smoe subarray of guys to the right of it.
    //in fact, it was a record min for all x < rt[i], rt[i] is closest st a[rt[i]] <= a[i]. so you -1 to that range.
    //and then an i appears. it's a record min for some subarray to the left of it.
    //it becomes a record min for all x > lt[i], where lt[i] is closest st a[lt[i]] <= a[i]. so you +1 to that range.
    //but you also need to calculate the value for i. and the value for i is just val[lt[i]] + 1
    vec.PB(0);
    FOR(i, 1, 2 * N + 2)
    {
        while(arr[vec.back()] > arr[i]) vec.pop_back();
        lt[i] = vec.back();
        vec.PB(i);
    }
    vec.clear();
    vec.PB(2 * N + 1);
    FORD(i, 2 * N + 1, 0)
    {
        while(arr[vec.back()] > arr[i]) vec.pop_back();
        rt[i] = vec.back();
        vec.PB(i);
    }
    solve(1, N, 1);
    // FOR(i, 0, 2 * N + 1)
    // {
    //     cerr << depth[i] << ' ';
    // }
    // cerr << endl;
    build(1, 0, 2 * N + 1);
    FOR(i, 0, N)
    {
        int res = query(1, 0, 2 * N + 1, i + 1, i + N);
        // cerr << i << " moves:";
        // FOR(j, i + 1, i + N + 1)
        // {
        //     cerr << ' ' << query(1, 0, 2 * N + 1, j, j);
        // }
        // cerr << endl;
        if (res < ans.fi) ans = {res, i};
        int idx;
        //now i + 1 disappears.
        idx = rt[i + 1];
        update(1, 0, 2 * N + 1, i + 1, idx - 1, -1);
        // cerr << "UPD " << i + 1 << ' ' << idx - 1 << " w " << -1 << endl;
        idx = lt[i + N + 1];
        update(1, 0, 2 * N + 1, idx + 1, i + N, 1);
        int cur = 1 + (idx == i + 1 ? 0 : query(1, 0, 2 * N + 1, idx, idx));
        // cerr << "cur = " << cur << " update " << i + N + 1 << " wtf " << query(1, 0, 2 * N + 1, i + N + 1, i + N + 1) << endl;
        update(1, 0, 2 * N + 1, i + N + 1, i + N + 1, cur);
    }
    cout << ans.fi << ' ' << ans.se << '\n';
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

template<class T, class U>
void ckmin(T &a, U b)
{
    if (a > b) a = b;
}

template<class T, class U>
void ckmax(T &a, U b)
{
    if (a < b) a = b;
}

#define MP make_pair
#define PB push_back
#define LB lower_bound
#define UB upper_bound
#define fi first
#define se second
#define SZ(x) ((int) (x).size())
#define ALL(x) (x).begin(), (x).end()
#define FOR(i, a, b) for (auto i = (a); i < (b); i++)
#define FORD(i, a, b) for (auto i = (a) - 1; i >= (b); i--)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<pii> vpi;
typedef vector<pll> vpl;

const int MAXN = 400013;
const int INF = 1000000007;

int N;
int arr[MAXN];
pii ans = {INF, INF};
int lt[MAXN], rt[MAXN];
int stor[20][MAXN];
int depth[MAXN];
int seg[3 * MAXN], lazy[3 * MAXN];
vi vec;

int comb(int i, int j)
{
    if (arr[i] == arr[j]) return i;
    return (arr[i] < arr[j] ? i : j);
}
int qry(int L, int R)
{
    int sz = 31 - __builtin_clz(R - L + 1);
    return comb(stor[sz][L], stor[sz][R - (1 << sz)] + 1);
}
void solve(int L, int R, int d)
{
    if (L > R) return;
    int idx = qry(L, R);
    depth[idx] = d;
    solve(L, idx - 1, d + 1);
    solve(idx + 1, R, d + 1);
}
void build(int w, int L, int R)
{
    lazy[w] = 0;
    if (L == R)
    {
        seg[w] = depth[L];
        return;
    }
    int mid = (L + R) >> 1;
    build(w << 1, L, mid);
    build(w << 1 | 1, mid + 1, R);
    seg[w] = max(seg[w << 1], seg[w << 1 | 1]);
}
void push(int w, int L, int R)
{
    if (lazy[w] == 0) return;
    seg[w] += lazy[w];
    if (L != R)
    {
        lazy[w << 1] += lazy[w];
        lazy[w << 1 | 1] += lazy[w];
    }
    lazy[w] = 0;
    return;
}
void update(int w, int L, int R, int a, int b, int v)
{
    push(w, L, R);
    if (b < L || R < a) return;
    if (a <= L && R <= b)
    {
        lazy[w] += v;
        push(w, L, R);
        return;
    }
    int mid = (L + R) >> 1;
    update(w << 1, L, mid, a, b, v);
    update(w << 1 | 1, mid + 1, R, a, b, v);
    seg[w] = max(seg[w << 1], seg[w << 1 | 1]);
}
int query(int w, int L, int R, int a, int b)
{
    push(w, L, R);
    if (a <= L && R <= b)
    {
        return seg[w];
    }
    int mid = (L + R) >> 1;
    if (b <= mid) return query(w << 1, L, mid, a, b);
    if (mid < a) return query(w << 1 | 1, mid + 1, R, a, b);
    return max(query(w << 1, L, mid, a, b), query(w << 1 | 1, mid + 1, R, a, b));
}

int32_t main()
{
    cout << fixed << setprecision(12);
    cerr << fixed << setprecision(4);
    ios_base::sync_with_stdio(false); cin.tie(0);
    cin >> N;
    FOR(i, 1, N + 1)
    {
        cin >> arr[i];
        arr[i + N] = arr[i];
    }
    FOR(i, 0, 2 * N + 2)
    {
        stor[0][i] = i;
    }
    FOR(i, 1, 20)
    {
        FOR(j, 0, 2 * N + 2 - (1 << i) + 1)
        {
            stor[i][j] = comb(stor[i - 1][j], stor[i - 1][j + (1 << (i - 1))]);
        }
    }
    //initially, you know each nodes depth.
    //then for each i that disappears, it was a record min for smoe subarray of guys to the right of it.
    //in fact, it was a record min for all x < rt[i], rt[i] is closest st a[rt[i]] <= a[i]. so you -1 to that range.
    //and then an i appears. it's a record min for some subarray to the left of it.
    //it becomes a record min for all x > lt[i], where lt[i] is closest st a[lt[i]] <= a[i]. so you +1 to that range.
    //but you also need to calculate the value for i. and the value for i is just val[lt[i]] + 1
    vec.PB(0);
    FOR(i, 1, 2 * N + 2)
    {
        while(arr[vec.back()] > arr[i]) vec.pop_back();
        lt[i] = vec.back();
        vec.PB(i);
    }
    vec.clear();
    vec.PB(2 * N + 1);
    FORD(i, 2 * N + 1, 0)
    {
        while(arr[vec.back()] > arr[i]) vec.pop_back();
        rt[i] = vec.back();
        vec.PB(i);
    }
    solve(1, N, 1);
    // FOR(i, 0, 2 * N + 1)
    // {
    //     cerr << depth[i] << ' ';
    // }
    // cerr << endl;
    build(1, 0, 2 * N + 1);
    FOR(i, 0, N)
    {
        int res = query(1, 0, 2 * N + 1, i + 1, i + N);
        // cerr << i << " moves:";
        // FOR(j, i + 1, i + N + 1)
        // {
        //     cerr << ' ' << query(1, 0, 2 * N + 1, j, j);
        // }
        // cerr << endl;
        if (res < ans.fi) ans = {res, i};
        int idx;
        //now i + 1 disappears.
        idx = rt[i + 1];
        update(1, 0, 2 * N + 1, i + 1, idx - 1, -1);
        // cerr << "UPD " << i + 1 << ' ' << idx - 1 << " w " << -1 << endl;
        idx = lt[i + N + 1];
        update(1, 0, 2 * N + 1, idx + 1, i + N, 1);
        int cur = 1 + (idx == i + 1 ? 0 : query(1, 0, 2 * N + 1, idx, idx));
        // cerr << "cur = " << cur << " update " << i + N + 1 << " wtf " << query(1, 0, 2 * N + 1, i + N + 1, i + N + 1) << endl;
        update(1, 0, 2 * N + 1, i + N + 1, i + N + 1, cur);
    }
    cout << ans.fi << ' ' << ans.se << '\n';
    return 0;
}


#include <bits/stdc++.h>

//#define int long long

#define pii pair<int, int>

#define x1 x1228
#define y1 y1228

#define left left228
#define right right228

#define pb push_back
#define eb emplace_back

#define mp make_pair

#define ff first
#define ss second

#define matr vector<vector<int> >

#define all(x) x.begin(), x.end()

using namespace std;
typedef long long ll;
typedef long double ld;

const int maxn = 4e5 + 7, mod = 998244353, inf = 1e9, MAXN = 1e6 + 7;
const double eps = 1e-9;
mt19937 rnd(time(0));

struct node {
    int mn, mx, push;
    node(int mn, int mx, int push) : mn(mn), mx(mx), push(push) {}
    node() : mn(inf), mx(-inf), push(0) {}
};

struct Tree {
    int len = 1;
    vector<node> tree;
    void build(int siz) {
        while (len < siz) len <<= 1;
        tree.resize(len + len - 1);
    }
    void push(int rt, int l, int r) {
        int push = tree[rt].push;
        tree[rt].push = 0;
        tree[rt].mx += push;
        if (l != r) {
            tree[rt * 2 + 1].push += push;
            tree[rt * 2 + 2].push += push;
        }
    }
    void relax(int rt) {
        tree[rt].mx = max(tree[rt * 2 + 1].mx, tree[rt * 2 + 2].mx);
    }
    int get_min(int l, int r, int l1, int r1, int rt) {
        if (l >= l1 && r <= r1) return tree[rt].mn;
        if (max(l, l1) > min(r, r1)) return inf;
        int tm = (l + r) / 2;
        return min(get_min(l, tm, l1, r1, rt * 2 + 1), get_min(tm + 1, r, l1, r1, rt * 2 + 2));
    }
    int get_max(int l, int r, int l1, int r1, int rt) {
        push(rt, l, r);
        if (l >= l1 && r <= r1) return tree[rt].mx;
        if (max(l, l1) > min(r, r1)) return -inf;
        int tm = (l + r) / 2;
        int p1 = get_max(l, tm, l1, r1, rt * 2 + 1);
        int p2 = get_max(tm + 1, r, l1, r1, rt * 2 + 2);
        relax(rt);
        return max(p1, p2);
    }
    void upd(int l, int r, int l1, int r1, int rt, int x) {
        push(rt, l, r);
        if (l >= l1 && r <= r1) {
            tree[rt].mx = x;
            return;
        }
        if (max(l, l1) > min(r, r1)) return;
        int tm = (l + r) / 2;
        upd(l, tm, l1, r1, rt * 2 + 1, x);
        upd(tm + 1, r, l1, r1, rt * 2 + 2, x);
        relax(rt);
    }
    void upd1(int l, int r, int l1, int r1, int rt, int x) {
        if (l >= l1 && r <= r1) {
            tree[rt].mn = x;
            return;
        }
        if (max(l, l1) > min(r, r1)) return;
        int tm = (l + r) / 2;
        upd1(l, tm, l1, r1, rt * 2 + 1, x);
        upd1(tm + 1, r, l1, r1, rt * 2 + 2, x);
        tree[rt].mn = min(tree[rt * 2 + 1].mn, tree[rt * 2 + 2].mn);
    }

    void add(int l, int r, int l1, int r1, int rt, int x) {
        push(rt, l, r);
        if (l >= l1 && r <= r1) {
            tree[rt].push += x;
            push(rt, l, r);
            return;
        }
        if (max(l, l1) > min(r, r1)) return;
        int tm = (l + r) / 2;
        add(l, tm, l1, r1, rt * 2 + 1, x);
        add(tm + 1, r, l1, r1, rt * 2 + 2, x);
        relax(rt);
    }
};
Tree req;
int n;
int perm[maxn];
int calc[maxn];
int idx[maxn];

int get_min(int l, int r) {
    return req.get_min(0, req.len - 1, l, r, 0);
}
int get_max(int l, int r) {
    return req.get_max(0, req.len - 1, l, r, 0);
}
void upd(int id, int x) {
    req.upd(0, req.len - 1, id, id, 0, x);
}
void upd1(int id, int x) {
    req.upd1(0, req.len - 1, id, id, 0, x);
}
void add(int l, int r, int x) {
    req.add(0, req.len - 1, l, r, 0, x);
}
void solve(int l, int r, int deep) {
    if (l > r) return;
    int mn = get_min(l, r);
    int id = idx[mn];
    calc[id] = deep;
    solve(l, id - 1, deep + 1);
    solve(id + 1, r, deep + 1);
}

void del(int id, int l, int r) {
    int l1 = l - 1;
    int m;
    int r1 = r + 1;
    while (l1 + 1 < r1) {
        m = (l1 + r1) / 2;
        if (get_min(l, m) >= perm[id]) l1 = m;
        else r1 = m;
    }
    add(l, l1, -1);
}

void recalc(int id, int l, int r) {
    int l1 = l - 1;
    int m;
    int r1 = r + 1;
    while (l1 + 1 < r1) {
        m = (l1 + r1) / 2;
        if (get_min(m, r) >= perm[id]) r1 = m;
        else l1 = m;
    }
    add(r1, r, 1);
    int val = 1;
    if (r1 != l) {
        val = get_max(r1 - 1, r1 - 1) + 1;
    }
    upd(id, val);
}

void solve() {
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> perm[i];
        idx[perm[i]] = i;
    }
    for (int i = n; i < 2 * n; ++i) {
        perm[i] = perm[i - n];
    }
    req.build(2 * n);
    for (int i = 0; i < 2 * n; ++i) {
        upd1(i, perm[i]);
    }
    solve(0, n - 1, 1);
    for (int i = 0; i < n; ++i) {
        upd(i, calc[i]);
    }
    int l = 0, r = n - 1;
    int ans = get_max(l, r);
    int shift = 0;
    for (int i = n; i < 2 * n; ++i) {
        l++;
        del(i - n, l, r);
        recalc(i, l, r);
        r++;
        int cur = get_max(l, r);
        if (ans > cur) {
            ans = cur;
            shift = i - n + 1;
        }
    }
    cout << ans << " " << shift;
}

signed main() {
#ifdef LOCAL
    freopen("TASK.in", "r", stdin);
    freopen("TASK.out", "w", stdout);
#else

#endif // LOCAL
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.precision(20);
    cout << fixed;
    int t = 1;
    for (int i = 0; i < t; ++i) {
        solve();
    }
    return 0;
}


#include <bits/stdc++.h>

#define int long long

#define pii pair<int, int>

#define x1 x1228
#define y1 y1228

#define left left228
#define right right228

#define pb push_back
#define eb emplace_back

#define mp make_pair

#define ff first
#define ss second

#define matr vector<vector<int> >

#define all(x) x.begin(), x.end()

using namespace std;
typedef long long ll;
typedef long double ld;

const int maxn = 3e5 + 7, mod = 998244353, inf = 1e18, MAXN = 1e6 + 7;
const double eps = 1e-9;
mt19937 rnd(time(0));

struct node {
    int mn, mx, push;
    node(int mn, int mx, int push) : mn(mn), mx(mx), push(push) {}
    node() : mn(inf), mx(-inf), push(0) {}
};

struct Tree {
    int len = 1;
    vector<node> tree;
    void build(int siz) {
        while (len < siz) len <<= 1;
        tree.resize(len + len - 1);
    }
    void push(int rt, int l, int r) {
        int push = tree[rt].push;
        tree[rt].push = 0;
        tree[rt].mx += push;
        if (l != r) {
            tree[rt * 2 + 1].push += push;
            tree[rt * 2 + 2].push += push;
        }
    }
    void relax(int rt) {
        tree[rt].mx = max(tree[rt * 2 + 1].mx, tree[rt * 2 + 2].mx);
    }
    int get_min(int l, int r, int l1, int r1, int rt) {
        if (l >= l1 && r <= r1) return tree[rt].mn;
        if (max(l, l1) > min(r, r1)) return inf;
        int tm = (l + r) / 2;
        return min(get_min(l, tm, l1, r1, rt * 2 + 1), get_min(tm + 1, r, l1, r1, rt * 2 + 2));
    }
    int get_max(int l, int r, int l1, int r1, int rt) {
        push(rt, l, r);
        if (l >= l1 && r <= r1) return tree[rt].mx;
        if (max(l, l1) > min(r, r1)) return -inf;
        int tm = (l + r) / 2;
        int p1 = get_max(l, tm, l1, r1, rt * 2 + 1);
        int p2 = get_max(tm + 1, r, l1, r1, rt * 2 + 2);
        relax(rt);
        return max(p1, p2);
    }
    void upd(int l, int r, int l1, int r1, int rt, int x) {
        push(rt, l, r);
        if (l >= l1 && r <= r1) {
            tree[rt].mx = x;
            return;
        }
        if (max(l, l1) > min(r, r1)) return;
        int tm = (l + r) / 2;
        upd(l, tm, l1, r1, rt * 2 + 1, x);
        upd(tm + 1, r, l1, r1, rt * 2 + 2, x);
        relax(rt);
    }
    void upd1(int l, int r, int l1, int r1, int rt, int x) {
        if (l >= l1 && r <= r1) {
            tree[rt].mn = x;
            return;
        }
        if (max(l, l1) > min(r, r1)) return;
        int tm = (l + r) / 2;
        upd1(l, tm, l1, r1, rt * 2 + 1, x);
        upd1(tm + 1, r, l1, r1, rt * 2 + 2, x);
        tree[rt].mn = min(tree[rt * 2 + 1].mn, tree[rt * 2 + 2].mn);
    }

    void add(int l, int r, int l1, int r1, int rt, int x) {
        push(rt, l, r);
        if (l >= l1 && r <= r1) {
            tree[rt].push += x;
            push(rt, l, r);
            return;
        }
        if (max(l, l1) > min(r, r1)) return;
        int tm = (l + r) / 2;
        add(l, tm, l1, r1, rt * 2 + 1, x);
        add(tm + 1, r, l1, r1, rt * 2 + 2, x);
        relax(rt);
    }
};
Tree req;
int n;
int perm[maxn];
int calc[maxn];
int idx[maxn];

int get_min(int l, int r) {
    return req.get_min(0, req.len - 1, l, r, 0);
}
int get_max(int l, int r) {
    return req.get_max(0, req.len - 1, l, r, 0);
}
void upd(int id, int x) {
    req.upd(0, req.len - 1, id, id, 0, x);
}
void upd1(int id, int x) {
    req.upd1(0, req.len - 1, id, id, 0, x);
}
void add(int l, int r, int x) {
    req.add(0, req.len - 1, l, r, 0, x);
}
void solve(int l, int r, int deep) {
    if (l > r) return;
    int mn = get_min(l, r);
    int id = idx[mn];
    calc[id] = deep;
    solve(l, id - 1, deep + 1);
    solve(id + 1, r, deep + 1);
}

void del(int id, int l, int r) {
    int l1 = l - 1;
    int m;
    int r1 = r + 1;
    while (l1 + 1 < r1) {
        m = (l1 + r1) / 2;
        if (get_min(l, m) >= perm[id]) l1 = m;
        else r1 = m;
    }
    add(l, l1, -1);
}

void recalc(int id, int l, int r) {
    int l1 = l - 1;
    int m;
    int r1 = r + 1;
    while (l1 + 1 < r1) {
        m = (l1 + r1) / 2;
        if (get_min(m, r) >= perm[id]) r1 = m;
        else l1 = m;
    }
    add(r1, r, 1);
    int val = 1;
    if (r1 != l) {
        val = get_max(r1 - 1, r1 - 1) + 1;
    }
    upd(id, val);
}

void solve() {
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> perm[i];
        idx[perm[i]] = i;
    }
    for (int i = n; i < 2 * n; ++i) {
        perm[i] = perm[i - n];
    }
    req.build(4 * n);
    for (int i = 0; i < 2 * n; ++i) {
        upd1(i, perm[i]);
    }
    solve(0, n - 1, 1);
    for (int i = 0; i < n; ++i) {
        upd(i, calc[i]);
    }
    int l = 0, r = n - 1;
    int ans = get_max(l, r);
    int shift = 0;
    for (int i = n; i < 2 * n; ++i) {
        l++;
        del(i - n, l, r);
        recalc(i, l, r);
        r++;
        int cur = get_max(l, r);
        if (ans > cur) {
            ans = cur;
            shift = i - n + 1;
        }
    }
    cout << ans << " " << shift;
}

signed main() {
#ifdef LOCAL
    freopen("TASK.in", "r", stdin);
    freopen("TASK.out", "w", stdout);
#else

#endif // LOCAL
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.precision(20);
    cout << fixed;
    int t = 1;
    for (int i = 0; i < t; ++i) {
        solve();
    }
    return 0;
}


#include <bits/stdc++.h>

#define int long long

#define pii pair<int, int>

#define x1 x1228
#define y1 y1228

#define left left228
#define right right228

#define pb push_back
#define eb emplace_back

#define mp make_pair

#define ff first
#define ss second

#define matr vector<vector<int> >

#define all(x) x.begin(), x.end()

using namespace std;
typedef long long ll;
typedef long double ld;

const int maxn = 4e5 + 7, mod = 998244353, inf = 1e18, MAXN = 1e6 + 7;
const double eps = 1e-9;
mt19937 rnd(time(0));

struct node {
    int mn, mx, push;
    node(int mn, int mx, int push) : mn(mn), mx(mx), push(push) {}
    node() : mn(inf), mx(-inf), push(0) {}
};

struct Tree {
    int len = 1;
    vector<node> tree;
    void build(int siz) {
        while (len < siz) len <<= 1;
        tree.resize(len + len - 1);
    }
    void push(int rt, int l, int r) {
        int push = tree[rt].push;
        tree[rt].push = 0;
        tree[rt].mx += push;
        if (l != r) {
            tree[rt * 2 + 1].push += push;
            tree[rt * 2 + 2].push += push;
        }
    }
    void relax(int rt) {
        tree[rt].mx = max(tree[rt * 2 + 1].mx, tree[rt * 2 + 2].mx);
    }
    int get_min(int l, int r, int l1, int r1, int rt) {
        if (l >= l1 && r <= r1) return tree[rt].mn;
        if (max(l, l1) > min(r, r1)) return inf;
        int tm = (l + r) / 2;
        return min(get_min(l, tm, l1, r1, rt * 2 + 1), get_min(tm + 1, r, l1, r1, rt * 2 + 2));
    }
    int get_max(int l, int r, int l1, int r1, int rt) {
        push(rt, l, r);
        if (l >= l1 && r <= r1) return tree[rt].mx;
        if (max(l, l1) > min(r, r1)) return -inf;
        int tm = (l + r) / 2;
        int p1 = get_max(l, tm, l1, r1, rt * 2 + 1);
        int p2 = get_max(tm + 1, r, l1, r1, rt * 2 + 2);
        relax(rt);
        return max(p1, p2);
    }
    void upd(int l, int r, int l1, int r1, int rt, int x) {
        push(rt, l, r);
        if (l >= l1 && r <= r1) {
            tree[rt].mx = x;
            return;
        }
        if (max(l, l1) > min(r, r1)) return;
        int tm = (l + r) / 2;
        upd(l, tm, l1, r1, rt * 2 + 1, x);
        upd(tm + 1, r, l1, r1, rt * 2 + 2, x);
        relax(rt);
    }
    void upd1(int l, int r, int l1, int r1, int rt, int x) {
        if (l >= l1 && r <= r1) {
            tree[rt].mn = x;
            return;
        }
        if (max(l, l1) > min(r, r1)) return;
        int tm = (l + r) / 2;
        upd1(l, tm, l1, r1, rt * 2 + 1, x);
        upd1(tm + 1, r, l1, r1, rt * 2 + 2, x);
        tree[rt].mn = min(tree[rt * 2 + 1].mn, tree[rt * 2 + 2].mn);
    }

    void add(int l, int r, int l1, int r1, int rt, int x) {
        push(rt, l, r);
        if (l >= l1 && r <= r1) {
            tree[rt].push += x;
            push(rt, l, r);
            return;
        }
        if (max(l, l1) > min(r, r1)) return;
        int tm = (l + r) / 2;
        add(l, tm, l1, r1, rt * 2 + 1, x);
        add(tm + 1, r, l1, r1, rt * 2 + 2, x);
        relax(rt);
    }
};
Tree req;
int n;
int perm[maxn];
int calc[maxn];
int idx[maxn];

int get_min(int l, int r) {
    return req.get_min(0, req.len - 1, l, r, 0);
}
int get_max(int l, int r) {
    return req.get_max(0, req.len - 1, l, r, 0);
}
void upd(int id, int x) {
    req.upd(0, req.len - 1, id, id, 0, x);
}
void upd1(int id, int x) {
    req.upd1(0, req.len - 1, id, id, 0, x);
}
void add(int l, int r, int x) {
    req.add(0, req.len - 1, l, r, 0, x);
}
void solve(int l, int r, int deep) {
    if (l > r) return;
    int mn = get_min(l, r);
    int id = idx[mn];
    calc[id] = deep;
    solve(l, id - 1, deep + 1);
    solve(id + 1, r, deep + 1);
}

void del(int id, int l, int r) {
    int l1 = l - 1;
    int m;
    int r1 = r + 1;
    while (l1 + 1 < r1) {
        m = (l1 + r1) / 2;
        if (get_min(l, m) >= perm[id]) l1 = m;
        else r1 = m;
    }
    add(l, l1, -1);
}

void recalc(int id, int l, int r) {
    int l1 = l - 1;
    int m;
    int r1 = r + 1;
    while (l1 + 1 < r1) {
        m = (l1 + r1) / 2;
        if (get_min(m, r) >= perm[id]) r1 = m;
        else l1 = m;
    }
    add(r1, r, 1);
    int val = 1;
    if (r1 != l) {
        val = get_max(r1 - 1, r1 - 1) + 1;
    }
    upd(id, val);
}

void solve() {
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> perm[i];
        idx[perm[i]] = i;
    }
    for (int i = n; i < 2 * n; ++i) {
        perm[i] = perm[i - n];
    }
    req.build(4 * n);
    for (int i = 0; i < 2 * n; ++i) {
        upd1(i, perm[i]);
    }
    solve(0, n - 1, 1);
    for (int i = 0; i < n; ++i) {
        upd(i, calc[i]);
    }
    int l = 0, r = n - 1;
    int ans = get_max(l, r);
    int shift = 0;
    for (int i = n; i < 2 * n; ++i) {
        l++;
        del(i - n, l, r);
        recalc(i, l, r);
        r++;
        int cur = get_max(l, r);
        if (ans > cur) {
            ans = cur;
            shift = i - n + 1;
        }
    }
    cout << ans << " " << shift;
}

signed main() {
#ifdef LOCAL
    freopen("TASK.in", "r", stdin);
    freopen("TASK.out", "w", stdout);
#else

#endif // LOCAL
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.precision(20);
    cout << fixed;
    int t = 1;
    for (int i = 0; i < t; ++i) {
        solve();
    }
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/trie_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
// freopen("k.in", "r", stdin);
// freopen("k.out", "w", stdout);
// clock_t c1 = clock();
// std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
mt19937 rnd(time(NULL));
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define ls ((x) << 1)
#define rs ((x) << 1 | 1)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<char, char> PCC;
typedef pair<ll, ll> PLL;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 4e5 + 7;
const int MAXM = 4e5 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-7;
const double pi = acos(-1.0);
int val[MAXN];
struct node
{
    int left, right; //区间端点
    int maxx, sum;   //看题目要求
    int lazy;
    void update(int x)
    {
        maxx += x;
        sum += (right - left + 1) * x;
        lazy += x;
    }
};
//建树，开四倍
struct Segement_Tree
{
    node T[MAXN << 2];
    void push_up(int x)
    {
        T[x].sum = T[x << 1].sum + T[x << 1 | 1].sum;
        T[x].maxx = max(T[x << 1].maxx, T[x << 1 | 1].maxx);
    }
    void push_down(int x)
    {
        ll lazeval = T[x].lazy;
        if (lazeval)
        {
            T[x << 1].update(lazeval);
            T[x << 1 | 1].update(lazeval);
            T[x].lazy = 0;
        }
    }
    //若原数组从a[1]~a[n]，调用build(1,1,n);
    void build(int x, int l, int r)
    {
        T[x].left = l;
        T[x].right = r;
        T[x].sum = T[x].maxx = T[x].lazy = 0;
        if (l == r) //若到达叶节点
        {
            T[x].sum = 0; //存储A数组的值
            T[x].maxx = 0;
        }
        else
        {
            int mid = (l + r) / 2;
            build(x << 1, l, mid);
            build(x << 1 | 1, mid + 1, r);
            push_up(x);
        }
        return;
    }
    //update(1,l,r,v)
    void update(int x, int l, int r, ll v) //区间更新
    {
        int L = T[x].left, R = T[x].right;
        if (l <= L && R <= r)
            T[x].update(v);
        else
        {
            push_down(x);
            int mid = (L + R) / 2;
            if (mid >= l)
                update(x << 1, l, r, v);
            if (r > mid)
                update(x << 1 | 1, l, r, v);
            push_up(x);
        }
    }
    //单点更新,更新pos点，调用add(1,pos,v)
    void add(int x, int pos, ll v) //当前更新的节点的编号为id（一般是以1为第一个编号）。pos为需要更新的点的位置，v为修改的值的大小
    {

        int L = T[x].left, R = T[x].right;
        if (L == pos && R == pos) //左右端点均和pos相等，说明找到了pos所在的叶子节点
        {
            T[x].sum += v;
            T[x].maxx += v;
            return; //找到了叶子节点就不需要在向下寻找了
        }
        push_down(x);
        int mid = (L + R) / 2;
        if (pos <= mid)
            add(x << 1, pos, v);
        else
            add(x << 1 | 1, pos, v); //寻找k所在的子区间
        push_up(x);                  //向上更新
    }
    //调用query_max(1,l,r)即可求[l,r]区间内元素的最大值
    ll query_max(int x, int l, int r)
    {
        int L = T[x].left, R = T[x].right;
        if (l == L && R == r)
            return T[x].maxx;
        else
        {
            push_down(x);
            int mid = (L + R) / 2;
            if (r <= mid)
                return query_max(x << 1, l, r);
            else if (l > mid)
                return query_max(x << 1 | 1, l, r);
            else
                return max(query_max(x << 1, l, mid), query_max(x << 1 | 1, mid + 1, r));
        }
    }
} T;
int L[MAXN], R[MAXN];
int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d", &val[i]), val[i + n] = val[i];
    stack<int> sta;
    val[2 * n + 1] = val[0] = 0;
    for (int i = 1; i <= 2 * n + 1; i++)
    {
        if (sta.empty())
        {
            sta.emplace(i);
            continue;
        }
        while ((!sta.empty()) && val[sta.top()] >= val[i])
        {
            R[sta.top()] = i - 1;
            sta.pop();
        }
        sta.emplace(i);
    }
    while (!sta.empty())
        sta.pop();
    for (int i = 2 * n; i >= 0; i--)
    {
        if (sta.empty())
        {
            sta.emplace(i);
            continue;
        }
        while ((!sta.empty()) && val[sta.top()] >= val[i])
        {
            L[sta.top()] = i + 1;
            sta.pop();
        }
        sta.emplace(i);
    }
    T.build(1, 1, 2 * n);
    for (int i = 1; i <= n; i++)
        T.update(1, L[i], R[i], 1);
    int minn_dep = T.query_max(1, 1, 2 * n);
    int cnt = 0;
    for (int i = 1; i < n; i++)
    {
        int st = i, ed = i + n;
        T.update(1, L[i], R[i], -1);
        T.update(1, L[ed], R[ed], 1);
        int res = T.query_max(1, 1, 2 * n);
        if (res < minn_dep)
        {
            minn_dep = res;
            cnt = i;
        }
    }
    printf("%d %d\n", minn_dep, cnt);
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/trie_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
// freopen("k.in", "r", stdin);
// freopen("k.out", "w", stdout);
// clock_t c1 = clock();
// std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
mt19937 rnd(time(NULL));
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define ls ((x) << 1)
#define rs ((x) << 1 | 1)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<char, char> PCC;
typedef pair<ll, ll> PLL;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 2e5 + 7;
const int MAXM = 4e5 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-7;
const double pi = acos(-1.0);
int val[MAXN];
struct node
{
    int left, right; //区间端点
    int maxx, sum;   //看题目要求
    int lazy;
    void update(int x)
    {
        maxx += x;
        sum += (right - left + 1) * x;
        lazy += x;
    }
};
//建树，开四倍
struct Segement_Tree
{
    node T[MAXN << 2];
    void push_up(int x)
    {
        T[x].sum = T[x << 1].sum + T[x << 1 | 1].sum;
        T[x].maxx = max(T[x << 1].maxx, T[x << 1 | 1].maxx);
    }
    void push_down(int x)
    {
        ll lazeval = T[x].lazy;
        if (lazeval)
        {
            T[x << 1].update(lazeval);
            T[x << 1 | 1].update(lazeval);
            T[x].lazy = 0;
        }
    }
    //若原数组从a[1]~a[n]，调用build(1,1,n);
    void build(int x, int l, int r)
    {
        T[x].left = l;
        T[x].right = r;
        T[x].sum = T[x].maxx = T[x].lazy = 0;
        if (l == r) //若到达叶节点
        {
            T[x].sum = 0; //存储A数组的值
            T[x].maxx = 0;
        }
        else
        {
            int mid = (l + r) / 2;
            build(x << 1, l, mid);
            build(x << 1 | 1, mid + 1, r);
            push_up(x);
        }
        return;
    }
    //update(1,l,r,v)
    void update(int x, int l, int r, ll v) //区间更新
    {
        int L = T[x].left, R = T[x].right;
        if (l <= L && R <= r)
            T[x].update(v);
        else
        {
            push_down(x);
            int mid = (L + R) / 2;
            if (mid >= l)
                update(x << 1, l, r, v);
            if (r > mid)
                update(x << 1 | 1, l, r, v);
            push_up(x);
        }
    }
    //单点更新,更新pos点，调用add(1,pos,v)
    void add(int x, int pos, ll v) //当前更新的节点的编号为id（一般是以1为第一个编号）。pos为需要更新的点的位置，v为修改的值的大小
    {

        int L = T[x].left, R = T[x].right;
        if (L == pos && R == pos) //左右端点均和pos相等，说明找到了pos所在的叶子节点
        {
            T[x].sum += v;
            T[x].maxx += v;
            return; //找到了叶子节点就不需要在向下寻找了
        }
        push_down(x);
        int mid = (L + R) / 2;
        if (pos <= mid)
            add(x << 1, pos, v);
        else
            add(x << 1 | 1, pos, v); //寻找k所在的子区间
        push_up(x);                  //向上更新
    }
    //调用query_max(1,l,r)即可求[l,r]区间内元素的最大值
    ll query_max(int x, int l, int r)
    {
        int L = T[x].left, R = T[x].right;
        if (l == L && R == r)
            return T[x].maxx;
        else
        {
            push_down(x);
            int mid = (L + R) / 2;
            if (r <= mid)
                return query_max(x << 1, l, r);
            else if (l > mid)
                return query_max(x << 1 | 1, l, r);
            else
                return max(query_max(x << 1, l, mid), query_max(x << 1 | 1, mid + 1, r));
        }
    }
} T;
int L[MAXN], R[MAXN];
int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d", &val[i]), val[i + n] = val[i];
    stack<int> sta;
    val[2 * n + 1] = val[0] = 0;
    for (int i = 1; i <= 2 * n + 1; i++)
    {
        if (sta.empty())
        {
            sta.emplace(i);
            continue;
        }
        while ((!sta.empty()) && val[sta.top()] >= val[i])
        {
            R[sta.top()] = i - 1;
            sta.pop();
        }
        sta.emplace(i);
    }
    while (!sta.empty())
        sta.pop();
    for (int i = 2 * n; i >= 0; i--)
    {
        if (sta.empty())
        {
            sta.emplace(i);
            continue;
        }
        while ((!sta.empty()) && val[sta.top()] >= val[i])
        {
            L[sta.top()] = i + 1;
            sta.pop();
        }
        sta.emplace(i);
    }
    T.build(1, 1, 2 * n);
    for (int i = 1; i <= n; i++)
        T.update(1, L[i], R[i], 1);
    int minn_dep = T.query_max(1, 1, 2 * n);
    int cnt = 0;
    for (int i = 1; i < n; i++)
    {
        int st = i, ed = i + n;
        T.update(1, L[i], R[i], -1);
        T.update(1, L[ed], R[ed], 1);
        int res = T.query_max(1, 1, 2 * n);
        if (res < minn_dep)
        {
            minn_dep = res;
            cnt = i;
        }
    }
    printf("%d %d\n", minn_dep, cnt);
    return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <vector>

#include <unordered_map>

using namespace std;

// BEGIN NO SAD
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()
typedef vector<int> vi;
// END NO SAD

typedef long long ll;
typedef pair<int, int> pii;

const int RAGETREE_DEPTH = 19;
const int RAGETREE_SZ = 1 << RAGETREE_DEPTH;
int ragetree[2 * RAGETREE_SZ]; // max
int ragetreeinc[2 * RAGETREE_SZ];
void apply(int idx, int val) {
  ragetree[idx] += val;
  if(idx < RAGETREE_SZ) ragetreeinc[idx] += val;
}
void push(int idx) {
  assert(idx >= RAGETREE_SZ);
  for(int d = RAGETREE_DEPTH; d > 0; d--) {
    int x = idx >> d;
    if(ragetreeinc[x]) {
      apply(2*x, ragetreeinc[x]);
      apply(2*x+1, ragetreeinc[x]);
      ragetreeinc[x] = 0;
    }
  }
}
void build(int idx) {
  assert(idx >= RAGETREE_SZ);
  while(idx > 1) {
    idx /= 2;
    ragetree[idx] = ragetreeinc[idx] + max(ragetree[2*idx], ragetree[2*idx+1]);
  }
}
void upd(int lhs, int rhs, int v) {
  if(lhs > rhs) return;
  lhs += RAGETREE_SZ;
  rhs += RAGETREE_SZ;
  int a = lhs;
  int b = rhs;
  while(lhs <= rhs) {
    if(lhs == rhs) {
      apply(lhs, v);
      break;
    }
    if(lhs%2) apply(lhs++, v);
    if(rhs%2==0) apply(rhs--, v);
    lhs /= 2;
    rhs /= 2;
  }
  build(a); build(b);
}
int qry(int lhs, int rhs) {
  lhs += RAGETREE_SZ;
  rhs += RAGETREE_SZ;
  push(lhs);
  push(rhs);
  int ret = 0;
  while(lhs <= rhs) {
    if(lhs == rhs) return max(ret, ragetree[lhs]);
    if(lhs%2) ret = max(ret, ragetree[lhs++]);
    if(rhs%2==0) ret = max(ret, ragetree[rhs--]);
    lhs /= 2;
    rhs /= 2;
  }
  return ret;
}

int l[2 * RAGETREE_SZ];
pii rmq[2 * RAGETREE_SZ][RAGETREE_DEPTH];
int n;
pii minqry(int lhs, int rhs) {
  // TODO: optimize to O(1)
  pii ret = {1e9, -1};
  int d = RAGETREE_DEPTH-1;
  while(lhs <= rhs) {
    if(lhs + (1<<d)-1 <= rhs) {
      ret = min(ret, rmq[lhs][d]);
      lhs += (1<<d);
    }
    d--;
  }
  return ret;
}
void solve() {
  cin >> n;
  for(int i = 0; i < n; i++) {
    cin >> l[i];
    l[i+n] = l[i];
    rmq[i][0] = {l[i], i};
    rmq[i+n][0] = {l[i+n], i+n};
  }
  for(int d = 1; d < RAGETREE_DEPTH; d++) {
    for(int i = 0; i + (1<<d) <= 2*n; i++) {
      rmq[i][d] = min(rmq[i][d-1], rmq[i+(1<<(d-1))][d-1]);
    }
  }
  queue<pii> q;
  q.push({0, n-1});
  while(sz(q)) {
    pii curr = q.front(); q.pop();
    if(curr.first >= curr.second) continue;
    pii best = minqry(curr.first, curr.second);
    upd(curr.first, best.second-1, 1);
    upd(best.second+1, curr.second, 1);
    q.push({curr.first, best.second-1});
    q.push({best.second+1, curr.second});
  }
  int lowdepth = qry(0, n-1);
  int shift = 0;
  for(int i = 0; i < n-1; i++) {
    int ni = i + n;
    if(l[i] == 1) {
      // the root has moved, nothing changes
    }
    else {
      // see what things on the left elevate
      int lhs = i;
      int rhs = ni-1;
      while(lhs < rhs) {
        int mid = (lhs+rhs+1)/2;
        if(minqry(i, mid).second == i) lhs = mid;
        else rhs = mid-1;
      }
      // anc is at lhs, lhs is the rightmost smallest
      upd(i+1, lhs, -1);
      // see what things on the right get shoved down
      lhs = i+1;
      rhs = ni;
      while(lhs < rhs) {
        int mid = (lhs+rhs)/2;
        if(minqry(mid, ni).second == ni) rhs = mid;
        else lhs = mid+1;
      }
      // anc is at lhs-1 again
      upd(ni, ni, qry(lhs-1, lhs-1));
      upd(lhs, ni, 1);
    }
    int canddepth = qry(i+1, i+n);
    if(canddepth < lowdepth) {
      lowdepth = canddepth;
      shift = i+1;
    }
  }
  cout << lowdepth+1 << " " << shift << "\n";
}

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


#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <vector>

#include <unordered_map>

using namespace std;

// BEGIN NO SAD
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()
typedef vector<int> vi;
// END NO SAD

typedef long long ll;
typedef pair<int, int> pii;

const int RAGETREE_DEPTH = 18;
const int RAGETREE_SZ = 1 << RAGETREE_DEPTH;
int ragetree[2 * RAGETREE_SZ]; // max
int ragetreeinc[2 * RAGETREE_SZ];
void apply(int idx, int val) {
  ragetree[idx] += val;
  if(idx < RAGETREE_SZ) ragetreeinc[idx] += val;
}
void push(int idx) {
  assert(idx >= RAGETREE_SZ);
  for(int d = RAGETREE_DEPTH; d > 0; d--) {
    int x = idx >> d;
    if(ragetreeinc[x]) {
      apply(2*x, ragetreeinc[x]);
      apply(2*x+1, ragetreeinc[x]);
      ragetreeinc[x] = 0;
    }
  }
}
void build(int idx) {
  assert(idx >= RAGETREE_SZ);
  while(idx > 1) {
    idx /= 2;
    ragetree[idx] = ragetreeinc[idx] + max(ragetree[2*idx], ragetree[2*idx+1]);
  }
}
void upd(int lhs, int rhs, int v) {
  if(lhs > rhs) return;
  lhs += RAGETREE_SZ;
  rhs += RAGETREE_SZ;
  int a = lhs;
  int b = rhs;
  while(lhs <= rhs) {
    if(lhs == rhs) {
      apply(lhs, v);
      break;
    }
    if(lhs%2) apply(lhs++, v);
    if(rhs%2==0) apply(rhs--, v);
    lhs /= 2;
    rhs /= 2;
  }
  build(a); build(b);
}
int qry(int lhs, int rhs) {
  lhs += RAGETREE_SZ;
  rhs += RAGETREE_SZ;
  push(lhs);
  push(rhs);
  int ret = 0;
  while(lhs <= rhs) {
    if(lhs == rhs) return max(ret, ragetree[lhs]);
    if(lhs%2) ret = max(ret, ragetree[lhs++]);
    if(rhs%2==0) ret = max(ret, ragetree[rhs--]);
    lhs /= 2;
    rhs /= 2;
  }
  return ret;
}

int l[2 * RAGETREE_SZ];
pii rmq[2 * RAGETREE_SZ][RAGETREE_DEPTH];
int n;
pii minqry(int lhs, int rhs) {
  // TODO: optimize to O(1)
  pii ret = {1e9, -1};
  int d = RAGETREE_DEPTH-1;
  while(lhs <= rhs) {
    if(lhs + (1<<d)-1 <= rhs) {
      ret = min(ret, rmq[lhs][d]);
      lhs += (1<<d);
    }
    d--;
  }
  return ret;
}
void solve() {
  cin >> n;
  for(int i = 0; i < n; i++) {
    cin >> l[i];
    l[i+n] = l[i];
    rmq[i][0] = {l[i], i};
    rmq[i+n][0] = {l[i+n], i+n};
  }
  for(int d = 1; d < RAGETREE_DEPTH; d++) {
    for(int i = 0; i + (1<<d) <= 2*n; i++) {
      rmq[i][d] = min(rmq[i][d-1], rmq[i+(1<<(d-1))][d-1]);
    }
  }
  queue<pii> q;
  q.push({0, n-1});
  while(sz(q)) {
    pii curr = q.front(); q.pop();
    if(curr.first >= curr.second) continue;
    pii best = minqry(curr.first, curr.second);
    upd(curr.first, best.second-1, 1);
    upd(best.second+1, curr.second, 1);
    q.push({curr.first, best.second-1});
    q.push({best.second+1, curr.second});
  }
  int lowdepth = qry(0, n-1);
  int shift = 0;
  for(int i = 0; i < n-1; i++) {
    int ni = i + n;
    if(l[i] == 1) {
      // the root has moved, nothing changes
    }
    else {
      // see what things on the left elevate
      int lhs = i;
      int rhs = ni-1;
      while(lhs < rhs) {
        int mid = (lhs+rhs+1)/2;
        if(minqry(i, mid).second == i) lhs = mid;
        else rhs = mid-1;
      }
      // anc is at lhs, lhs is the rightmost smallest
      upd(i+1, lhs, -1);
      // see what things on the right get shoved down
      lhs = i+1;
      rhs = ni;
      while(lhs < rhs) {
        int mid = (lhs+rhs)/2;
        if(minqry(mid, ni).second == ni) rhs = mid;
        else lhs = mid+1;
      }
      // anc is at lhs-1 again
      upd(ni, ni, qry(lhs-1, lhs-1));
      upd(lhs, ni, 1);
    }
    int canddepth = qry(i+1, i+n);
    if(canddepth < lowdepth) {
      lowdepth = canddepth;
      shift = i+1;
    }
  }
  cout << lowdepth+1 << " " << shift << "\n";
}

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


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

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}

void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

#define lf double
#define ll long long

#define pii pair<int,int >
#define vec vector<int >

#define pb push_back
#define mp make_pair
#define fr first
#define sc second

#define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++)

const int maxn = 2e5+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 1e9+7;

int n,a[maxn],b[maxn],p,g[2][maxn];

#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)

struct segment_tree {
    int mx[maxn<<2],tag[maxn<<2];

    void clear() {
        memset(mx,0,sizeof mx);
        memset(tag,0,sizeof tag);
    }

    void push(int p,int x) {tag[p]+=x,mx[p]+=x;}

    void pushdown(int p) {
        if(tag[p]) push(ls,tag[p]),push(rs,tag[p]),tag[p]=0;
    }

    void update(int p) {mx[p]=max(mx[ls],mx[rs]);}

    void modify(int p,int l,int r,int x,int y,int v) {
        if(y<x) return ;
        if(x<=l&&r<=y) return push(p,v),void();
        pushdown(p);
        if(x<=mid) modify(ls,l,mid,x,y,v);
        if(y>mid) modify(rs,mid+1,r,x,y,v);
        update(p);
    }

    int query(int p,int l,int r,int x,int y) {
        // printf("query :: %d %d %d %d %d\n",p,l,r,x,y);cerr<<"";
        if(y<x) return 0;
        if(x<=l&&r<=y) return mx[p];
        pushdown(p);int ans=0;
        if(x<=mid) ans=max(ans,query(ls,l,mid,x,y));
        if(y>mid) ans=max(ans,query(rs,mid+1,r,x,y));
        return ans;
    }

    int get(int p,int l,int r,int x) {
        // printf("get :: %d %d %d %d\n",l,r,x,mx[p]);
        if(l==r) return mx[p];
        if(x<=mid) return get(ls,l,mid,x);
        if(mx[rs]>mx[ls]) return get(rs,mid+1,r,x);
        return get(ls,l,mid,x);
    }
}T,w;

void solve(int *r,int *f) {
    // for(int i=1;i<=n-1;i++) printf("%d ",r[i]);puts("");
    T.clear();w.clear();
    for(int i=1;i<=n-1;i++) {
        // cerr<<i<<endl;
        int x=w.get(1,1,n,r[i]);
        // printf("??? :: %d %d %d\n",i,r[i],x);
        if(!x) {
            w.modify(1,1,n,r[i],r[i],i);
            f[i]=T.query(1,1,n-1,1,i-1)+1;
            // cerr<<f[i]<<endl;
            T.modify(1,1,n-1,1,i,1);
            continue;
        }
        w.modify(1,1,n,r[i],r[i],i);
        T.modify(1,1,n-1,x+1,i-1,1);
        // printf("get :: %d %d\n",i,T.query(1,1,n-1,x,x)+1);
        T.modify(1,1,n-1,i,i,T.query(1,1,n-1,x,x)+1);
        f[i]=T.query(1,1,n-1,1,i);
        // printf("get :: %d %d\n",i,f[i]);
    }
}

int main() {
    read(n);for(int i=1;i<=n;i++) {read(b[i]);if(b[i]==1) p=i;}
    if(n==1) {puts("1 0");return 0;}
    for(int i=p+1;i<=n;i++) a[i-p]=b[i];
    for(int i=1;i<p;i++) a[n-p+i]=b[i];int mn=1e9,t=0;
    solve(a,g[0]);reverse(a+1,a+n);solve(a,g[1]);reverse(g[1]+1,g[1]+n);
    for(int i=1;i<n-1;i++) {
        if(max(g[0][i],g[1][i+1])<mn) mn=max(g[0][i],g[1][i+1]),t=i;//printf("%d %d\n",p,t);
        // printf("%d %d %d\n",i,g[0][i],g[1][i]);
    }
    // printf("%d %d\n",p,t);
    printf("%d %d\n",mn+1,(p-1+t+1)%n);
    return 0;
}


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

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}

void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

#define lf double
#define ll long long

#define pii pair<int,int >
#define vec vector<int >

#define pb push_back
#define mp make_pair
#define fr first
#define sc second

#define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++)

const int maxn = 2e5+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 1e9+7;

int n,a[maxn],b[maxn],p,g[2][maxn];

#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)

struct segment_tree {
    int mx[maxn<<2],tag[maxn<<2];

    void clear() {
        memset(mx,0,sizeof mx);
        memset(tag,0,sizeof tag);
    }

    void push(int p,int x) {tag[p]+=x,mx[p]+=x;}

    void pushdown(int p) {
        if(tag[p]) push(ls,tag[p]),push(rs,tag[p]),tag[p]=0;
    }

    void update(int p) {mx[p]=max(mx[ls],mx[rs]);}

    void modify(int p,int l,int r,int x,int y,int v) {
        if(y<x) return ;
        if(x<=l&&r<=y) return push(p,v),void();
        pushdown(p);
        if(x<=mid) modify(ls,l,mid,x,y,v);
        if(y>mid) modify(rs,mid+1,r,x,y,v);
        update(p);
    }

    int query(int p,int l,int r,int x,int y) {
        if(y<x) return 0;
        if(x<=l&&r<=y) return mx[p];
        pushdown(p);int ans=0;
        if(x<=mid) ans=max(ans,query(ls,l,mid,x,y));
        if(y>mid) ans=max(ans,query(rs,mid+1,r,x,y));
        return ans;
    }
}T;

void solve(int *r,int *f) {
    T.clear();set<pii > s;
    for(int i=1;i<=n-1;i++) {
        // cerr<<i<<endl;
        if(s.empty()||s.rbegin()->fr<r[i]) {
            s.insert(mp(r[i],i));f[i]=T.query(1,1,n-1,1,i-1)+1;
            // cerr<<f[i]<<endl;
            T.modify(1,1,n-1,i,i,f[i]);
            continue;
        }
        int x=(--s.lower_bound(mp(r[i],i)))->sc;
        T.modify(1,1,n-1,x+1,i-1,1);
        T.modify(1,1,n-1,i,i,T.query(1,1,n-1,x,x)+1);
        f[i]=T.query(1,1,n-1,1,i);
    }
}

int main() {
    read(n);for(int i=1;i<=n;i++) {read(b[i]);if(b[i]==1) p=i;}
    for(int i=p+1;i<=n;i++) a[i-p]=b[i];
    for(int i=1;i<p;i++) a[n-p+i]=b[i];int mn=1e9,t=0;
    solve(a,g[0]);reverse(a+1,a+n);solve(a,g[1]);reverse(g[1]+1,g[1]+n);
    for(int i=1;i<n-1;i++) if(max(g[0][i],g[1][i+1])<mn) mn=max(g[0][i],g[1][i+1]),t=i;//printf("%d %d\n",p,t);
    printf("%d %d\n",mn+1,(p-1+n-1-t)%n);
    return 0;
}


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

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}

void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

#define lf double
#define ll long long

#define pii pair<int,int >
#define vec vector<int >

#define pb push_back
#define mp make_pair
#define fr first
#define sc second

#define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++)

const int maxn = 2e5+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 1e9+7;

int n,a[maxn],b[maxn],p,g[2][maxn];

#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)

struct segment_tree {
    int mx[maxn<<2],tag[maxn<<2];

    void clear() {
        memset(mx,0,sizeof mx);
        memset(tag,0,sizeof tag);
    }

    void push(int p,int x) {tag[p]+=x,mx[p]+=x;}

    void pushdown(int p) {
        if(tag[p]) push(ls,tag[p]),push(rs,tag[p]),tag[p]=0;
    }

    void update(int p) {mx[p]=max(mx[ls],mx[rs]);}

    void modify(int p,int l,int r,int x,int y,int v) {
        if(y<x) return ;
        if(x<=l&&r<=y) return push(p,v),void();
        pushdown(p);
        if(x<=mid) modify(ls,l,mid,x,y,v);
        if(y>mid) modify(rs,mid+1,r,x,y,v);
        update(p);
    }

    int query(int p,int l,int r,int x,int y) {
        // printf("query :: %d %d %d %d %d\n",p,l,r,x,y);cerr<<"";
        if(y<x) return 0;
        if(x<=l&&r<=y) return mx[p];
        pushdown(p);int ans=0;
        if(x<=mid) ans=max(ans,query(ls,l,mid,x,y));
        if(y>mid) ans=max(ans,query(rs,mid+1,r,x,y));
        return ans;
    }
}T;

void solve(int *r,int *f) {
    T.clear();set<pii > s;
    for(int i=1;i<=n-1;i++) {
        // cerr<<i<<endl;
        if(s.empty()||s.begin()->fr>r[i]) {
            s.insert(mp(r[i],i));f[i]=T.query(1,1,n-1,1,i-1)+1;
            // cerr<<f[i]<<endl;
            T.modify(1,1,n-1,i,i,f[i]);
            continue;
        }
        int x=(--s.lower_bound(mp(r[i],i)))->sc;
        T.modify(1,1,n-1,x+1,i-1,1);
        T.modify(1,1,n-1,i,i,T.query(1,1,n-1,x,x)+1);
        f[i]=T.query(1,1,n-1,1,i);
    }
}

int main() {
    read(n);for(int i=1;i<=n;i++) {read(b[i]);if(b[i]==1) p=i;}
    for(int i=p+1;i<=n;i++) a[i-p]=b[i];
    for(int i=1;i<p;i++) a[n-p+i]=b[i];int mn=1e9,t=0;
    solve(a,g[0]);reverse(a+1,a+n);solve(a,g[1]);reverse(g[1]+1,g[1]+n);
    for(int i=1;i<n-1;i++) if(max(g[0][i],g[1][i+1])<mn) mn=max(g[0][i],g[1][i+1]),t=i;//printf("%d %d\n",p,t);
    printf("%d %d\n",mn+1,(p-1+n-1-t)%n);
    return 0;
}


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

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}

void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

#define lf double
#define ll long long

#define pii pair<int,int >
#define vec vector<int >

#define pb push_back
#define mp make_pair
#define fr first
#define sc second

#define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++)

const int maxn = 2e5+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 1e9+7;

int n,a[maxn],b[maxn],p,g[2][maxn];

#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)

struct segment_tree {
    int mx[maxn<<2],tag[maxn<<2];

    void clear() {
        memset(mx,0,sizeof mx);
        memset(tag,0,sizeof tag);
    }

    void push(int p,int x) {tag[p]+=x,mx[p]+=x;}

    void pushdown(int p) {
        if(tag[p]) push(ls,tag[p]),push(rs,tag[p]),tag[p]=0;
    }

    void update(int p) {mx[p]=max(mx[ls],mx[rs]);}

    void modify(int p,int l,int r,int x,int y,int v) {
        if(y<x) return ;
        if(x<=l&&r<=y) return push(p,v),void();
        pushdown(p);
        if(x<=mid) modify(ls,l,mid,x,y,v);
        if(y>mid) modify(rs,mid+1,r,x,y,v);
        update(p);
    }

    int query(int p,int l,int r,int x,int y) {
        // printf("query :: %d %d %d %d %d\n",p,l,r,x,y);cerr<<"";
        if(y<x) return 0;
        if(x<=l&&r<=y) return mx[p];
        pushdown(p);int ans=0;
        if(x<=mid) ans=max(ans,query(ls,l,mid,x,y));
        if(y>mid) ans=max(ans,query(rs,mid+1,r,x,y));
        return ans;
    }

    // int get(int p,int l,int r,int x) {
    //     printf("get :: %d %d %d %d\n",l,r,x,mx[p]);
    //     if(l==r) return mx[p];
    //     if(x<=mid) return get(ls,l,mid,x);
    //     if(mx[rs]>mx[ls]) return get(rs,mid+1,r,x);
    //     return get(ls,l,mid,x);
    // }
}T,w;

void solve(int *r,int *f) {
    // for(int i=1;i<=n-1;i++) printf("%d ",r[i]);puts("");
    T.clear();w.clear();
    for(int i=1;i<=n-1;i++) {
        // cerr<<i<<endl;
        int x=w.query(1,1,n,1,r[i]);
        // printf("??? :: %d %d %d\n",i,r[i],x);
        if(!x) {
            w.modify(1,1,n,r[i],r[i],i);
            f[i]=T.query(1,1,n-1,1,i-1)+1;
            // cerr<<f[i]<<endl;
            T.modify(1,1,n-1,1,i,1);
            continue;
        }
        w.modify(1,1,n,r[i],r[i],i);
        T.modify(1,1,n-1,x+1,i-1,1);
        // printf("get :: %d %d\n",i,T.query(1,1,n-1,x,x)+1);
        T.modify(1,1,n-1,i,i,T.query(1,1,n-1,x,x)+1);
        f[i]=T.query(1,1,n-1,1,i);
        // printf("get :: %d %d\n",i,f[i]);
    }
}

int main() {
    read(n);for(int i=1;i<=n;i++) {read(b[i]);if(b[i]==1) p=i;}
    if(n==1) {puts("1 0");return 0;}
    for(int i=p+1;i<=n;i++) a[i-p]=b[i];
    for(int i=1;i<p;i++) a[n-p+i]=b[i];int mn=1e9,t=0;
    solve(a,g[0]);reverse(a+1,a+n);solve(a,g[1]);reverse(g[1]+1,g[1]+n);
    for(int i=1;i<n-1;i++) {
        if(max(g[0][i],g[1][i+1])<mn) mn=max(g[0][i],g[1][i+1]),t=i;//printf("%d %d\n",p,t);
        // printf("%d %d %d\n",i,g[0][i],g[1][i]);
    }
    // printf("%d %d\n",p,t);
    printf("%d %d\n",mn+1,(p-1+t+1)%n);
    return 0;
}