#ifndef LOCAL #pragma GCC optimize("O3") #endif #include using namespace std; #define sim template muu & operator<<( #define ris return *this #define R22(r) sim> typename enable_if<1 r sizeof(dud(0)),muu&>::type operator<<(c g) { sim> struct rge {c b, e;}; sim> rge range(c i, c j) {return rge{i, j};} sim> auto dud(c*r)->decltype(cerr << *r); sim> char dud(...); struct muu { #ifdef LOCAL stringstream a; ~muu() {cerr << a.str() << endl;} R22(<) a << boolalpha << g; ris;} R22(==) ris << range(begin(g), end(g));} sim mor rge u) { a << "["; for (c i = u.b; i != u.e; ++i) *this << ", " + 2 * (i == u.b) << *i; ris << "]"; } sim, class b mor pair r){ris << "(" << r.first << ", " << r.second << ")";} #else sim mor const c&){ris;} #endif }; #define debug muu() << __FUNCTION__ << "#" << __LINE__ << ": " #define imie(r...) "[" #r ": " << (r) << "] " #define range(a, b) "[[" #a ", " #b "): " << range(a, b) << "] " #define arr(a, i) "[" #a imie(i) ": " << a[i] << "] " using ll = long long; using ld = long double; using pii = pair ; const int z = 1024 * 256; int drzewo_tab_max[z * 2 + 7]; int drzewo_tab_min[z * 2 + 7]; const int nax = 2 * 100007; int N; int czytaj(int* drzewo, int a, int b) { a += z - 1, b += z + 1; int ret = -1337133713; while (a != b - 1) { if (a % 2 == 0) ret = max(ret, drzewo[a + 1]); if (b % 2 == 1) ret = max(ret, drzewo[b - 1]); a /= 2, b /= 2; } return ret; } void wrzuc(int* drzewo, int a, int war) { a += z; drzewo[a] = war; a /= 2; while (a != 0) { drzewo[a] = max(drzewo[a * 2], drzewo[a * 2 + 1]); a /= 2; } } int tab[nax]; int mniejsze[nax]; set odp; int pierwsze[nax], ostatnie[nax], drugie[nax]; void przelicz(bool odw) { set juz; set> spoko, spoko_mniej; juz.insert(0); memset(pierwsze, 0, sizeof(pierwsze)); memset(drugie, 0, sizeof(drugie)); memset(ostatnie, 0, sizeof(ostatnie)); for (int i = 1; i <= N; i++) { if (pierwsze[tab[i]] == 0) { pierwsze[tab[i]] = i; ostatnie[tab[i]] = i; } else { if (drugie[tab[i]] == 0) drugie[tab[i]] = i; ostatnie[tab[i]] = i; } } for (int i = 1; i <= N; i++) { wrzuc(drzewo_tab_max, i, tab[i]); wrzuc(drzewo_tab_min, i, -tab[i]); auto it = --juz.lower_bound(tab[i]); mniejsze[i] = *it; if (*it != 0) spoko.insert(tab[i]); if (juz.upper_bound(tab[i]) != juz.end()) spoko_mniej.insert(*juz.upper_bound(tab[i])); if (spoko.upper_bound(tab[i]) != spoko.end()) { debug << "321"; odp.insert(odw ? "321" : "123"); } if (spoko_mniej.upper_bound(tab[i]) != spoko_mniej.end()) { debug << "312"; odp.insert(odw ? "312" : "213"); } juz.insert(tab[i]); debug << imie(juz) imie(spoko) imie(spoko_mniej); } debug << range(mniejsze + 1, mniejsze + N + 1); int mini = 1337133713; for (int i = N; i >= 1; i--) { mini = min(mini, tab[i]); if (mniejsze[i] > mini && tab[i] > mini) { debug << "132"; odp.insert(odw ? "132" : "231"); } } for (int i = 1; i <= N; i++) { // 121 212 int a = pierwsze[tab[i]], b = ostatnie[tab[i]]; debug << imie(tab[i]) imie(a) imie(b); if (b > a + 1) { if (czytaj(drzewo_tab_max, a + 1, b - 1) > tab[i]) { debug << "121"; odp.insert("121"); } if (-czytaj(drzewo_tab_min, a + 1, b - 1) < tab[i]) { debug << "212"; odp.insert("212"); } } // 112 221 b = drugie[tab[i]]; if (b != N && a < b) { if (czytaj(drzewo_tab_max, b + 1, N) > tab[i]) { debug << "112"; odp.insert(odw ? "211" : "112"); } if (-czytaj(drzewo_tab_min, b + 1, N) < tab[i]) { debug << "221"; odp.insert(odw ? "122" : "221"); } } } for (int i = 1; i <= N; i++) { if (drugie[tab[i]] != 0 && drugie[tab[i]] != ostatnie[tab[i]]) { debug << imie(tab[i]); debug << 111; odp.insert("111"); } } } pii ord[nax]; int main() { scanf("%d", &N); for (int i = 1; i <= N; i++) { scanf("%d", &tab[i]); ord[i] = {tab[i], i}; } debug << range(tab + 1, tab + N + 1); sort(ord + 1, ord + N + 1); int nu = 0; for (int i = 1; i <= N; ++i) { if (ord[i].first != ord[i - 1].first) nu++; tab[ord[i].second] = nu; } debug << range(tab + 1, tab + N + 1); przelicz(false); for (int i = 1; i <= N / 2; i++) swap(tab[i], tab[N - i + 1]); przelicz(true); for (auto it : odp) { printf("%s\n", it.c_str()); } }