#include using namespace std; #define fio ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); typedef long long ll; ll n; struct SegmentTree { vector mx, mn, A; ll N; ll left(ll p) { return p << 1; } ll right(ll p) { return p << 1 | 1; } void build(ll p, ll L, ll R) { if(L == R) { mx[p] = mn[p] = A[L]; return; } build(left(p), L, (L + R) >> 1); build(right(p), ((L + R) >> 1) + 1, R); mn[p] = min(mn[left(p)], mn[right(p)]); mx[p] = max(mx[left(p)], mx[right(p)]); } ll mn_query(ll p, ll L, ll R, ll i, ll j) { if(L > j || R < i) return LONG_LONG_MAX; if(L >= i && R <= j) return mn[p]; ll p1 = mn_query(left(p), L, (L + R) >> 1, i, j); ll p2 = mn_query(right(p), ((L + R) >> 1) + 1, R, i, j); return min(p1, p2); } ll mx_query(ll p, ll L, ll R, ll i, ll j) { if(L > j || R < i) return LONG_LONG_MIN; if(L >= i && R <= j) return mx[p]; ll p1 = mx_query(left(p), L, (L + R) >> 1, i, j); ll p2 = mx_query(right(p), ((L + R) >> 1) + 1, R, i, j); return max(p1, p2); } SegmentTree(vector &_A) { A = _A; N = A.size(); mx.assign(4 * N, 0); mn.assign(4 * N, 0); build(1, 0, N - 1); } ll mn_query(ll i, ll j) { return mn_query(1, 0, N - 1, i, j); } ll mx_query(ll i, ll j) { return mx_query(1, 0, N - 1, i, j); } }; map cnt; set res; void check_same() { for(auto &a: cnt) { if(a.second >= 3) { res.insert("111"); return; } } } int main() { fio cin >> n; vector v(n); multiset passed, to_pass; map first_seen, last_seen; for(int i = 0; i < n; i++) { cin >> v[i]; cnt[v[i]]++; to_pass.insert(v[i]); last_seen[v[i]] = i; } SegmentTree st(v); unordered_set seen; for(int i = 0; i < n; i++) { ll mn_left = st.mn_query(0, i - 1); ll mn_right = st.mn_query(i + 1, n - 1); ll mx_left = st.mx_query(0, i - 1); ll mx_right = st.mx_query(i + 1, n - 1); if(mn_left < v[i] && v[i] < mx_right) res.insert("123"); if(mx_left > v[i] && v[i] > mn_right) res.insert("321"); to_pass.erase(to_pass.find(v[i])); auto t = to_pass.upper_bound(mn_left); if(t != to_pass.end()) { if (mn_left < v[i] && v[i] > *t) res.insert("132"); } t = passed.upper_bound(v[i]); if(t != passed.end()) { if(mx_right > *t) res.insert("213"); } t = passed.upper_bound(mn_right); if(t != passed.end()) { if(*t < v[i]) res.insert("231"); } t = to_pass.upper_bound(v[i]); if(t != to_pass.end()) { if(*t < mx_left) res.insert("312"); } if(mx_left > v[i] && v[i] > mn_right) res.insert("321"); bool seen_me = first_seen.find(v[i]) != first_seen.end(); bool will_see_me = (last_seen.find(v[i]) != last_seen.end()) && last_seen[v[i]] > i; if(seen_me) { ll mx = st.mx_query(first_seen[v[i]] + 1, i - 1); if(mx > v[i]) res.insert("121"); } if(seen_me && mx_right > v[i]) res.insert("112"); if(will_see_me && mx_left > v[i]) res.insert("211"); if(seen_me && mn_right < v[i]) res.insert("221"); if(seen_me) { ll fsm = first_seen[v[i]]; if (fsm < i && st.mn_query(fsm + 1, i - 1) < v[i]) res.insert("212"); } ll lsm = last_seen[v[i]]; if(lsm > i && v[i] > mn_left) res.insert("122"); if(!seen_me) first_seen[v[i]] = i; passed.insert(v[i]); } check_same(); for(auto &x: res) { cout << x << '\n'; } return 0; }