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 inf = 10234567;

int n; 
int P[200055];
int value[200055];
int totalPhigh = 0;

struct state{ int maxX, maxY, highX, highY; };
state cur = {0,0,0,0};

struct segment{
	int tree[400105];
	int N;
	
	void init(int _N){
		N = _N;
		for(int i = 0;i <= 2*N;i++) tree[i] = -inf;
	}
	
	void update(int i, int x){
		i += N;
		tree[i] = x;
		i >>= 1;
		while(i > 0){
			tree[i] = max(tree[i<<1], tree[i<<1|1]);
			i >>= 1;
		}
	}
	
	int query(int l, int r){
		int res = -inf;
		for(l += N, r += N;l < r;l >>= 1, r >>= 1){
			if(l&1) res = max(res, tree[l++]);
			if(r&1) res = max(res, tree[--r]);
		}
		return res;
	}
} odd, even;

bool verify(state S){
	
	///let a be all Phigh
	int target = totalPhigh + S.highX - S.highY;
	if(target >= 0){ ///IMPT
		int best; ///look for best with same parity as target
		if(target % 2 == 0) best = even.query(S.maxY, n+1);
		else best = odd.query(S.maxY, n+1);
		if(best >= target) return true;
	}
	
	///let b be all Phigh
	target = totalPhigh - S.highX + S.highY;
	if(target >= 0){ ///IMPT
		int best; ///look for best with same parity as target
		if(target % 2 == 0) best = even.query(S.maxX, n+1);
		else best = odd.query(S.maxX, n+1);
		if(best >= target) return true;
	}
	
	return false;
}

state addTo(state ori, int value, bool isX){ ///function to transition from one state to another
	state nxt = ori; 
	if(isX){
		if(value > nxt.maxX){
			nxt.maxX = value;
			nxt.highX++;
		}
	}
	else{
		if(value > nxt.maxY){
			nxt.maxY = value;
			nxt.highY++;
		}
	}
	return nxt;
}

	
int main(){
	ios_base::sync_with_stdio(false); cin.tie(0);
	
	cin >> n;
	for(int i = 1;i <= n;i++) cin >> P[i];
	P[0] = 0;
	
	int maxValue = 0;
	for(int i = 0;i <= n;i++){
		if(maxValue < P[i]){
			maxValue = P[i];
			value[i] = 2;
			totalPhigh++;
		}
		else value[i] = 1;
	}
	
	odd.init(n+2); even.init(n+2);
	
	///do LDS from the back (LIS in left to right)
	for(int i = n;i >= 1;i--){
		int best1 = odd.query(P[i]+1, n+1) + value[i]; ///take from odd
		int best2 = even.query(P[i]+1, n+1) + value[i]; ///take from even
		int best3 = value[i]; ///take for first time
		
		int bestOdd = -inf, bestEven = -inf;
		
		if(best1 % 2 == 0) bestEven = max(bestEven, best1);
		else bestOdd = max(bestOdd, best1);
		
		if(best2 % 2 == 0) bestEven = max(bestEven, best2);
		else bestOdd = max(bestOdd, best2);
		
		if(best3 % 2 == 0) bestEven = max(bestEven, best3);
		else bestOdd = max(bestOdd, best3);
		
		even.update(P[i], bestEven);
		odd.update(P[i], bestOdd);
	}
		
		

	string ans = "";
	for(int i = 1;i <= n;i++){
		///we undo the dp table (stored in segment tree)
		odd.update(P[i], -inf);
		even.update(P[i], -inf);
		
		if(value[i] == 2) totalPhigh--; 
		
		if(P[i] < cur.maxX && P[i] < cur.maxY){ ///IMPT
			ans += '0';
			continue;
		}
		
		///try to add to X
		state nxt = addTo(cur, P[i], true);
		
		if(verify(nxt)){ ///check if can be done
			ans += '0';
			cur = nxt;
		}
		else{
			ans += '1';
			cur = addTo(cur, P[i], false);
		}
	}
	
	if(cur.highX != cur.highY) ans = "-1";
	cout << ans;
}