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++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

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

namespace TYC
{
	typedef long long ll;
	const int N = 2e5 + 5;

	int n, flag, P[N], Mark[N], LIS[N][2];
	char Ans[N << 1];

	inline int read()
	{
		int x = 0;
		int f = 0, ch = getchar();
		while (!isdigit(ch))
			f |= (ch == '-'), ch = getchar();
		while (isdigit(ch))
			x = x * 10 + ch - '0', ch = getchar();
		return f ? -x : x;
	}

	struct tree
	{	
		int mxl, v[N << 3];
		void modify(const int p, const int w, const int t, const int o = 1, const int l = 1, const int r = n);
		int query(const int w, const int o = 1, const int l = 1, const int r = n);
		int getmax(const int p, const int w, const int o = 1, const int l = 1, const int r = n);
	} T[2], V[2];

#define ls (o << 1)
#define rs (o << 1 | 1)

	void tree::modify(const int p, const int w, const int t, const int o, const int l, const int r)
	{
		if (l == r)
			return void(v[o] = t ? max(v[o], w) : w);
		int mid = (l + r) >> 1;
		p <= mid ? modify(p, w, t, ls, l, mid) : modify(p, w, t, rs, mid + 1, r);
		v[o] = max(v[ls], v[rs]);
	}

	int tree::query(const int w, const int o, const int l, const int r)
	{
		if (v[o] < w)
			return 0;
		if (l == r)
			return l;
		int mid = (l + r) >> 1;
		return v[rs] > w ? query(w, rs, mid + 1, r) : query(w, ls, l, mid);
	}

	int tree::getmax(const int s, const int e, const int o, const int l, const int r)
	{
		if (s <= l && r <= e)
			return v[o];
		int mid = (l + r) >> 1, ans = 0;
		if (s <= mid)
			ans = max(ans, getmax(s, e, ls, l, mid));
		if (e > mid)
			ans = max(ans, getmax(s, e, rs, mid + 1, r));
		return ans;
	}

#undef ls
#undef rs

	void getlis()
	{
		for (int i = n; i; i--)
			if (Mark[i])
			{
				for (int k = 0; k < 2; k++)
				{
					int p = T[k].query(P[i]) + 2;
					T[k].mxl = max(T[k].mxl, p);
					T[k].modify(p, P[i], 1);
					LIS[i][k] = p;
				}
			}
			else
			{
				for (int k = 0; k < 2; k++)
				{
					int p = T[k].query(P[i]) + 1;
					if ((p & 1) == k)
					{
						T[k ^ 1].mxl = max(T[k ^ 1].mxl, p);
						T[k ^ 1].modify(p, P[i], 1); 
						LIS[i][k] = p;
					}
					else if (k)
					{
						T[k].modify(1, P[i], 1);
						T[k].mxl = max(T[k].mxl, 1);
						LIS[i][k] = 1;
					}
				}
			}
	}

	inline bool check(int cx, int hx, int cy, const int hy, int tot, const int i, const int type)
	{
		if (P[i] > hx)
			hx = P[i], cx++;
		int v = type ? cy + tot - cx : cx + tot - cy;
		return v >= 0 && V[v & 1].getmax(type ? hx : hy, n) >= v;
	}

	void solve(const int type)
	{
		static char R[N];
		int cx = 0, cy = 0, hx = 0, hy = 0, tot = 0;
		for (int i = 1; i <= n; i++)
		{
			V[0].modify(P[i], LIS[i][0], 0);
			V[1].modify(P[i], LIS[i][1], 0);
			tot += Mark[i];
		}

		for (int i = 1; i <= n; i++)
		{
			V[0].modify(P[i], 0, 0);
			V[1].modify(P[i], 0, 0);
			tot -= Mark[i];
			if (check(cx, hx, cy, hy, tot, i, type))
			{
				R[i] = '0';
				if (P[i] > hx)
					hx = P[i], cx++;
			}
			else
			{
				R[i] = '1';
				if (P[i] > hy)
					hy = P[i], cy++;
			}
		}
		if (cx != cy)
			return;
		if (!flag)
			flag = 1, memcpy(Ans, R, sizeof(char[n + 1]));
		else
		{
			for (int i = 1; i <= n; i++)
				if (R[i] != Ans[i])
				{
					if (R[i] < Ans[i])
						memcpy(Ans, R, sizeof(char[n + 1]));
					break;
				}
		}
	}

	void work()
	{
		n = read();
		for (int i = 1; i <= n; i++)
			P[i] = read();
		for (int i = 1, mx = 0; i <= n; i++)
			if (P[i] > mx)
				mx = P[i], Mark[i] = 1;
		getlis();
		solve(0);
		solve(1);
		puts(flag ? Ans + 1 : "-1");
	}
}

int main()
{
	TYC::work();
	return 0;
}