// includes {{{
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<tuple>
#include<cmath>
#include<random>
#include<cassert>
// }}}
// #include<bits/stdc++.h>
using namespace std;
using ll = long long;

// TODO : update
// NOTE : query in range!
/// --- PersistentSegmentTree Library {{{ ///

template < class Monoid >
struct PersistentSegTree {
private:
  using T = typename Monoid::T;
  int n;
  vector< T > data;
  vector< int > lch, rch;
  int lastRoot = 0;

public:
  PersistentSegTree() : n(0) {}
  PersistentSegTree(int t) : data(1, Monoid::identity()), lch(1, 0), rch(1, 0) {
    n = 1;
    while(n < t) n <<= 1;
  }
  template < class InputIter,
           class = typename iterator_traits< InputIter >::value_type >
             PersistentSegTree(InputIter first, InputIter last)
             : PersistentSegTree(distance(first, last)) {
               assign(first, last);
             }
  int set(int i, const T &v, int root = -1) {
    if(root == -1) root = lastRoot;
    int k = make();
    set(i, v, 0, n, k, root);
    lastRoot = k;
    return k;
  }
  template < class InputIter,
           class = typename iterator_traits< InputIter >::value_type >
             void assign(InputIter first, InputIter last) {
               assert(n >= distance(first, last));
               data.resize(n * 2 - 1, Monoid::identity());
               lch.resize(n * 2 - 1, 0);
               rch.resize(n * 2 - 1, 0);
               copy(first, last, begin(data) + n - 1);
               for(int i = n - 2; i >= 0; i--) {
                 data[i] = Monoid::op(data[lch[i] = i * 2 + 1], data[rch[i] = i * 2 + 2]);
               }
             }
  void reserve(int qsize) {
    int h = log(n);
    data.reserve(n * 2 - 1 + qsize * h);
    lch.reserve(n * 2 - 1 + qsize * h);
    rch.reserve(n * 2 - 1 + qsize * h);
  }
  void set(int i, const T &v, int l, int r, int k, int prevK) {
    if(r - l == 1) {
      data[k] = v;
      return;
    }
    lch[k] = lch[prevK];
    rch[k] = rch[prevK];
    int x = make(); //// important where to calc
    if(i < ((l + r) >> 1)) {
      lch[k] = x;
      set(i, v, l, (l + r) >> 1, lch[k], lch[prevK]);
    } else {
      rch[k] = x;
      set(i, v, (l + r) >> 1, r, rch[k], rch[prevK]);
    }
    data[k] = Monoid::op(data[lch[k]], data[rch[k]]);
  }
  T get(int i, int root = -1) { return query(i, i + 1, root); }
  T query(int a, int b, int root = -1) {
    if(root == -1) root = lastRoot;
    return query(a, b, 0, n, root);
  }
  T query(int a, int b, int l, int r, int k) {
    if(k == 0) return Monoid::identity();
    if(b <= l || r <= a) return Monoid::identity();
    if(a <= l && r <= b) return data[k];
    return Monoid::op(query(a, b, l, (l + r) >> 1, lch[k]),
        query(a, b, (l + r) >> 1, r, rch[k]));
  }

private:
  int make() {
    data.emplace_back(Monoid::identity());
    lch.emplace_back(0);
    rch.emplace_back(0);
    return data.size() - 1;
  }
  int log(int x) {
    int t = 0;
    while(x) x >>= 1, t++;
    return t;
  }
};

/// }}}--- ///

/// --- Monoid examples {{{ ///

struct Nothing {
  using T = char;
  using M = char;
  static constexpr T op(const T &, const T &) { return 0; }
  static constexpr T identity() { return 0; }
  template < class X >
    static constexpr X actInto(const M &, ll, ll, const X &x) {
      return x;
    }
};

struct RangeMin {
  using T = ll;
  static T op(const T &a, const T &b) { return min(a, b); }
  static constexpr T identity() { return numeric_limits< T >::max(); }
};

struct RangeMax {
  using T = ll;
  static T op(const T &a, const T &b) { return max(a, b); }
  static constexpr T identity() { return numeric_limits< T >::min(); }
};

struct RangeSum {
  using T = ll;
  static T op(const T &a, const T &b) { return a + b; }
  static constexpr T identity() { return 0; }
};

/// }}}--- ///

using Seg = PersistentSegTree< RangeMax >;
vector<Seg> ecas(2, Seg(212345));

int main() {
  std::ios::sync_with_stdio(false), std::cin.tie(0);
  int n;
  cin >> n;
  vector<int> a(n);
  vector<pair<int, int>> v;
  for(int i = 0; i < n; i++) cin >> a[i], v.emplace_back(a[i], i);
  vector<int> isH(n);
  int highest = 0;
  int Q = 0;
  vector<int> q(n);
  for(int i = 0; i < n; i++){
    q[i] = Q;
    if((highest = max(highest, a[i])) == a[i]) {
      isH[i] = 1;
      Q++;
    }
  }

  sort(rbegin(v), rend(v));

  vector<map<int, int>> time(2);
  for(int i = 0; i < n; i++) {
    int j; tie(ignore, j) = v[i];
    if(isH[j]) {
      time[0][n - 1 - i] = ecas[0].set(j, max(ecas[0].query(j + 1, n) + 2, 2ll));
      time[1][n - 1 - i] = ecas[1].set(j, max(ecas[1].query(j + 1, n) + 2, -ll(1e9) - 1));
    } else {
      // 同符号に何もしない，もあるけど後の使い方的に不要
      time[0][n - 1 - i] = ecas[0].set(j, max(ecas[1].query(j + 1, n) + 1, 0ll)); /////
      time[1][n - 1 - i] = ecas[1].set(j, max(ecas[0].query(j + 1, n) + 1, 1ll)); //////// j + 1
    }
  }

  auto can = [&](int x, int y, int i, int h) {
    if(i == n) return x == y;
    int T = x - y + (Q - q[i]);
    if(T < 0) return false;
    int p = T % 2;
    ll r = ecas[p].query(i, n, time[p][h]);
    if(r < 0) r = 0; //////
    return T <= r;
  };
  
  int c0 = 0, c1 = 0;
  int h0 = 0, h1 = 0;
  string ans;
  if(!can(0, 0, 0, h0)) return cout << -1 << endl, 0;
  for(int i = 0; i < n; i++) {
    int a0 = h0 < a[i], a1 = h1 < a[i];
    // 0がすべてHだと仮定
    // 1を決めていく
    // 0 : c0 + Q - k
    // 1 : c1 + k + m
    // 2k + m = c0 - c1 + Q
    // 1がryも同様
    int sel;
    if(can(c0 + a0, c1, i + 1, h1)) sel = 0;
    else if(can(c1, c0 + a0, i + 1, max(h0, a[i]))) sel = 0; /////// max // 変わらん
    else sel = 1;
    if(sel == 1) {
      ans += "1";
      h1 = max(h1, a[i]);
      if(a1) c1++;
    } else {
      ans += "0";
      h0 = max(h0, a[i]);
      if(a0) c0++;
    }
  }

  cout << ans << endl;
  return 0;
}



Measured memory_bytes: 165584