#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <tuple>
using namespace std;

const int INF = 1000000000;

struct type {
	int num;
	int posNum;
	type(int _num = -INF, int _posNum = -1) {
		num = _num;
		posNum = _posNum;
	}
	type operator+(const type& rhs) const {
		if (posNum == -1) return rhs;
		if (rhs.posNum == -1) return *this;
		if (num > rhs.num) return *this;
		if (num < rhs.num) return rhs;
		return type(num, min(posNum, rhs.posNum));
	}
};

struct update {
	int sum, v;
	update(int _sum = 0, int _v = -1) {
		sum = _sum;
		v = _v;
	}
	update operator+(const update& rhs) const {
		return update(sum + rhs.sum, max(v, rhs.v));
	}
	type operator()(const type& rhs) const {
		return type(rhs.num + sum, (v != -1)?v:rhs.posNum);
	}
	bool operator!=(const update &rhs) const {
		return sum != rhs.sum;
	}
};

template<typename T, typename U> struct seg_tree_lazy {
	int S, H;

	T def;
	vector<T> value;

	U noop;
	vector<U> prop;

	seg_tree_lazy<T, U>(int _S, T _def = T(), U _noop = U()) {
		S = _S, def = _def, noop = _noop;
		H = 32 - __builtin_clz(S);

		value.resize(2 * S + 1, def);
		prop.resize(2 * S + 1, noop);
	}

	void apply(int i, U update) {
		value[i] = update(value[i]);
		if(i < S) prop[i] = prop[i] + update;
	}

	void rebuild(int i) {
		for (int l = i/2; l; l /= 2) {
			T combined = value[2*l] + value[2*l+1];
			value[l] = prop[l](combined);
		}
	}

	void propagate(int i) {
		for (int h = H; h > 0; h--) {
			int l = i >> h;
			if (prop[l] != noop) {
				apply(2*l, prop[l]);
				apply(2*l+1, prop[l]);
				prop[l] = noop;
			}
		}
	}

	void upd(int i, int j, U update) {
		i += S, j += S;
		propagate(i), propagate(j);

		for (int l = i, r = j; l <= r; l /= 2, r /= 2) {
			if((l&1) == 1) apply(l++, update);
			if((r&1) == 0) apply(r--, update);
		}

		rebuild(i), rebuild(j);
	}

	T query(int i, int j){
		i += S, j += S;
		propagate(i), propagate(j);

		T res = def;
		for(; i <= j; i /= 2, j /= 2){
			if((i&1) == 1) res = res + value[i++];
			if((j&1) == 0) res = res + value[j--];
		}
		return res;
	}
};



int main() {
	int N;
	scanf("%d", &N);
	vector<int> V(N);
	for (int &x : V) {
		scanf("%d", &x); x--;
	}
	bool inorder = true;
	for (int i = 0; i < N; i++) if (V[i] != i) inorder = false;
	if (inorder) {
		printf("Cool Array\n");
		return 0;
	}
	vector<int> invV(N);
	for (int i = 0; i < N; i++) invV[V[i]] = i;
	int S = N;
	while (__builtin_popcount(S) != 1) S++;
	seg_tree_lazy<type, update> segtree(S);

	// find special Js
	vector<int> J, VJ;
	int last = -1;
	for (int j = N-1; j >= 0; j--) {
		if (last != -1 && V[j] > last) continue;
		J.push_back(j);
		VJ.push_back(V[j]);
		last = V[j];
		segtree.upd(j, j, update(INF, j));
	}
	reverse(VJ.begin(), VJ.end());
	reverse(J.begin(), J.end());
	// initialize with "> V[j]" for all j
	for (int i = 0; i < N; i++) {
		int pos = upper_bound(VJ.begin(), VJ.end(), V[i]) - VJ.begin();
		if (pos == J.size()) continue;
		pos = max(J[pos], i+1);
		segtree.upd(pos, S-1, update(-1));
	}

	last = -1;
	tuple<int, int, int> best{INF, 0, 0};
	for (int i = 0; i < N; i++) {
		int pos = upper_bound(VJ.begin(), VJ.end(), V[i]) - VJ.begin();
		if (pos < J.size()) {
			pos = max(J[pos], i+1);
			segtree.upd(pos, S-1, update(1));
		}
		
		if (last != -1 && V[i] < last) {
			segtree.upd(i + 1, S-1, update(-1));
			continue;
		}
		for (int k = last + 1; k <= V[i]; k++) {
			if (invV[k] <= i) continue;
			segtree.upd(invV[k] + 1, S-1, update(1));
		}

		// include i itself
		pos = upper_bound(VJ.begin(), VJ.end(), V[i]) - VJ.begin();
		int limsup = S-1;
		if (pos != VJ.size()) limsup = J[pos]-1;
		int liminf = i+1;
		if (limsup >= liminf) segtree.upd(liminf, limsup, update(1));
		type ans = segtree.query(i+1, N-1);
		best = min(best, tuple<int, int, int>{-ans.num, i, ans.posNum});
		last = V[i];
		if (limsup >= liminf) segtree.upd(liminf, limsup, update(-1));

	}
	printf("%d %d\n", get<1>(best) + 1, get<2>(best) + 1);
	return 0;
}