Problem:
Score : 1400 points

Problem Statement

You are given P, a permutation of (1,\ 2,\ ...\ N).

A string S of length N consisting of 0 and 1 is a good string when it meets the following criterion:

The sequences X and Y are constructed as follows:

First, let X and Y be empty sequences.

For each i=1,\ 2,\ ...\ N, in this order, append P_i to the end of X if S_i= 0, and append it to the end of Y if S_i= 1.

If X and Y have the same number of high elements, S is a good string.
Here, the i-th element of a sequence is called high when that element is the largest among the elements from the 1-st to i-th element in the sequence.

Determine if there exists a good string. If it exists, find the lexicographically smallest such string.

Constraints

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

1 \leq P_i \leq N

P_1,\ P_2,\ ...\ P_N are all distinct.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
P_1 P_2 ... P_N

Output

If a good string does not exist, print -1.
If it exists, print the lexicographically smallest such string.

Sample Input 1

6
3 1 4 6 2 5

Sample Output 1

001001

Let S= 001001. Then, X=(3,\ 1,\ 6,\ 2) and Y=(4,\ 5).
The high elements in X is the first and third elements, and the high elements in Y is the first and second elements.
As they have the same number of high elements, 001001 is a good string.
There is no good string that is lexicographically smaller than this, so the answer is 001001.

Sample Input 2

5
1 2 3 4 5

Sample Output 2

-1

Sample Input 3

7
1 3 2 5 6 4 7

Sample Output 3

0001101

Sample Input 4

30
1 2 6 3 5 7 9 8 11 12 10 13 16 23 15 18 14 24 22 26 19 21 28 17 4 27 29 25 20 30

Sample Output 4

000000000001100101010010011101

Solution in C++ (GCC 9.2.1) (judge verdict: Accepted)

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

struct segment_tree {
	segment_tree() {}
	segment_tree(int _n) {
		n = _n;
		N = 1; while(N - 1 <= n) N <<= 1;
		a = vector<int>(N << 1, 0);
	}

	void M(int i, int x) {
		a[i |= N] = x;
		for (i >>= 1; i; i >>= 1) a[i] = max(a[i << 1], a[(i << 1) | 1]);
		return;
	}

	int Q(int i) {
		int x = 0;
		for (int s = (i | N) - 1, t = (n | N) + 1; s ^ t ^ 1; s >>= 1, t >>= 1) {
			if(~s & 1) x = max(x, a[s ^ 1]);
			if(t & 1) x = max(x, a[t ^ 1]);
		}
		return x;
	}
	private :
	vector<int> a;
	int n, N;
};

int main() {
	ios::sync_with_stdio(false);
	int n; cin >> n;
	vector<int> a(n), s(n, 0);
	vector<bool> h(n);
	for (int mx = 0, i = 0; i < n; ++i) cin >> a[i], h[i] = (a[i] > mx), mx = max(mx, a[i]);
	for (int i = n - 1; i; --i) s[i - 1] = s[i] + h[i];

	array<segment_tree, 2> seg = {segment_tree(n), segment_tree(n)};
	for (int i = n - 1; ~i; --i) {
		array<int, 2> g = {seg[0].Q(a[i]), seg[1].Q(a[i])};
		if(h[i]) {
			seg[0].M(a[i], g[0] + 2);
			if(g[1] & 1) seg[1].M(a[i], g[1] + 2);
		}
		else {
			seg[1].M(a[i], g[0] + 1);
			if(g[1] & 1) seg[0].M(a[i], g[1] + 1);
		}
	}

	int max0(0), max1(0), cnt0(0), cnt1(0);
	string ans("");
	for (int x, i = 0; i < n; ++i) {
		x = a[i];
		seg[0].M(x, 0); seg[1].M(x, 0);

		auto check = [&](int max0, int cnt0, int max1, int cnt1) {
			static array<int, 2> g;
			g = {seg[0].Q(max0), seg[1].Q(max0)};
			if(cnt0 + cnt1 + s[i] & 1) {
				if(g[1] & 1) {
					if(cnt0 + 1 <= cnt1 + s[i] && cnt0 + g[1] >= cnt1 + s[i]) return true;
				}
			}
			else {
				if(cnt0 <= cnt1 + s[i] && cnt0 + g[0] >= cnt1 + s[i]) return true;
			}
			g = {seg[0].Q(max1), seg[1].Q(max1)};
			if(cnt0 + cnt1 + s[i] & 1) {
				if(g[1] & 1) {
					if(cnt1 + 1 <= cnt0 + s[i] && cnt1 + g[1] >= cnt0 + s[i]) return true;
				}
			}
			else {
				if(cnt1 <= cnt0 + s[i] && cnt1 + g[0] >= cnt0 + s[i]) return true;
			}
			return false;
		};

		if(check(max(max0, x), cnt0 + (x > max0), max1, cnt1)) { ans += "0"; max0 = max(max0, x); cnt0 += (x == max0); }
		else { ans += "1"; max1 = max(max1, x); cnt1 += (x == max1); }
	}
	if(cnt0 == cnt1) cout << ans << endl;
	else cout << "-1\n";
	return 0;
}