Problem: 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.

Examples

Input

6
3 1 4 6 2 5


Output

001001


Input

5
1 2 3 4 5


Output

-1


Input

7
1 3 2 5 6 4 7


Output

0001101


Input

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


Output

000000000001100101010010011101

Solution (in CPP):

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

const int N=2e5+100,inf=2e7;
int n,p[N],f[2][N],s[N],c[N],cnt1,cnt2,mx1,mx2;
char Ans[N];

struct SegmentTree
{
	#define Mx N<<2
	#define ls k<<1
	#define rs k<<1|1
	int L[Mx],R[Mx],mx[Mx];
	void build(int k,int l,int r)
	{
		L[k]=l, R[k]=r, mx[k]=-inf;
		if(l == r) return;
		int mid=(l+r)>>1;
		build(ls,l,mid), build(rs,mid+1,r);
	}
	void Modify(int k,int x,int sum)
	{
		//cout<<L[k]<<" "<<R[k]<<" "<<x<<" "<<sum<<endl;
		if(L[k] == R[k]) {mx[k]=sum; return;}
		int mid=(L[k]+R[k])>>1;
		if(x<=mid) Modify(ls,x,sum);
		else Modify(rs,x,sum);
		mx[k]=max(mx[ls],mx[rs]);
	}
	int Query(int k,int l,int r)
	{	
		if(l<=L[k] && R[k]<=r) return mx[k];
		int mid=(L[k]+R[k])>>1,ret=-inf;
		if(l<=mid) ret=max(ret,Query(ls,l,r));
		if(r>mid) ret=max(ret,Query(rs,l,r));
		return ret;
	}
}Tr[2];
bool chk(int MX,int Q)
{
	if(Q<0) return 0;
	//cout<<MX<<" "<<Q<<" "<<Tr[1].Query(1,max(1,MX),n)<<endl;
	if(Q&1) return Tr[1].Query(1,max(1,MX),n)>=Q;
	return Tr[0].Query(1,max(1,MX),n)>=Q;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		scanf("%d",&p[i]), s[i]=max(p[i],s[i-1]),
		c[i] = (s[i] == p[i])?2:1;
	//for(int i=1;i<=n;++i) cout<<c[i]<<" "; puts("");
	for(int i=n;i>=1;--i)
	{
		s[i]=s[i+1];
		if(c[i] == 2) ++s[i];
	}
	Tr[0].build(1,1,n), Tr[1].build(1,1,n);
	for(int i=n;i>=1;--i)
	{
		f[0][i]=(c[i] == 2)?2:-inf, f[1][i]=(c[i] == 1)?1:-inf;
		if(c[i] == 2)
			f[0][i]=max(Tr[0].Query(1,p[i],n)+2,f[0][i]),
			f[1][i]=max(Tr[1].Query(1,p[i],n)+2,f[1][i]);
		else
			f[0][i]=max(Tr[1].Query(1,p[i],n)+1,f[0][i]),
			f[1][i]=max(Tr[0].Query(1,p[i],n)+1,f[1][i]);
		Tr[0].Modify(1,p[i],f[0][i]), Tr[1].Modify(1,p[i],f[1][i]);
		
	}
	for(int i=1;i<=n;++i)
	{
		Tr[0].Modify(1,p[i],0), Tr[1].Modify(1,p[i],-inf);
		//cout<<f[0][i]<<" "<<f[1][i]<<" "<<Tr[1].Query(1,1,n)<<endl;
		int c1=cnt1, c2=cnt2;
	//放在X后
		c1=(p[i]>mx1)?c1+1:c1;
		if(chk(mx2,c1-c2+s[i+1]))
		{
			Ans[i]='0', cnt1=c1, mx1=max(p[i],mx1); continue;
		}
		if(chk(max(p[i],mx1),c2-c1+s[i+1]))
		{
			Ans[i]='0', cnt1=c1, mx1=max(p[i],mx1); continue;
		}
	//放在Y后
		c1=cnt1, c2=(mx2<p[i])?c2+1:c2;
		Ans[i]='1', cnt2=c2, mx2=max(mx2,p[i]);
	}
	if(cnt1 != cnt2) {puts("-1"); return 0;}
	puts(Ans+1);
	return 0;
}