#include <bits/stdc++.h>

using namespace std;

//#define int long long
#define all(v) (v).begin(), (v).end()
#define resz(v, ...) (v).clear(), (v).resize(__VA_ARGS__)
#define reps(i, m, n) for(int i = (int)(m); i < (int)(n); i++)
#define rep(i, n) reps(i, 0, n)

template<class T1, class T2> void chmin(T1 &a, T2 b){if(a>b)a=b;}
template<class T1, class T2> void chmax(T1 &a, T2 b){if(a<b)a=b;}

typedef pair<int, int> Pi;
typedef tuple<int, int, int> Ti;
typedef vector<int> vint;

//const int inf = 1LL << 55;
const int mod = 1e9 + 7;

struct SegmentTree {
  vector< set<int> > dataO, dataP;
  int sz;
  SegmentTree(int n) {
    sz = 1; while(sz < n) sz<<=1;
    resz(dataO, 2*sz-1);
    resz(dataP, 2*sz-1);
  }
  void update(int a, int b, int c, int k, int l, int r) {
    if(r <= a || b <= l) return;
    if(a <= l && r <= b) {
      dataO[k].insert(c);
      return;
    }
    update(a, b, c, 2*k+1, l, (l+r)/2);
    update(a, b, c, 2*k+2, (l+r)/2, r);
    dataP[k].insert(c);
  }
  void update(int a, int b, int c) {
    update(a, b, c, 0, 0, sz);
  }
  bool query(int a, int b, int c, int d, int k, int l, int r) {
    if(r <= a || b <= l) return true;
    bool vO = dataO[k].lower_bound(c) == dataO[k].upper_bound(d);
    if(!vO) return false;
    bool vP = dataP[k].lower_bound(c) == dataP[k].upper_bound(d);
    if(a <= l && r <= b) return vP;
    bool vl = query(a, b, c, d, 2*k+1, l, (l+r)/2);
    bool vr = query(a, b, c, d, 2*k+2, (l+r)/2, r);
    return vl&&vr;
  }
  bool query(int a, int b, int c, int d) {
    return query(a, b, c, d, 0, 0, sz);
  }
};

signed main()
{
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);

  int N;
  cin >> N;
  vint px(N), py(N), qx(N), qy(N);
  vint cx, cy;
  rep(i, N) {
    cin >> px[i] >> py[i] >> qx[i] >> qy[i];
    cx.push_back(px[i]); cy.push_back(py[i]);
    cx.push_back(qx[i]); cy.push_back(qy[i]);
  }
  sort(all(cx));
  cx.erase(unique(all(cx)), end(cx));
  sort(all(cy));
  cy.erase(unique(all(cy)), end(cy));

  rep(i, N) {
    px[i] = lower_bound(all(cx), px[i])-begin(cx);
    py[i] = lower_bound(all(cy), py[i])-begin(cy);
    qx[i] = lower_bound(all(cx), qx[i])-begin(cx);
    qy[i] = lower_bound(all(cy), qy[i])-begin(cy);
    if(px[i] > qx[i]) swap(px[i], qx[i]);
    if(py[i] > qy[i]) swap(py[i], qy[i]);
  }

  SegmentTree segX(cx.size()), segY(cy.size());

  rep(i, N) {
    if(segX.query(px[i], qx[i]+1, py[i], qy[i]) &&
       segY.query(py[i], qy[i]+1, px[i], qx[i])) {
      cout << 1 << endl;
      if(px[i] == qx[i]) segY.update(py[i], qy[i]+1, px[i]);
      else segX.update(px[i], qx[i]+1, py[i]);
    } else {
      cout << 0 << endl;
    }
  }
  return 0;
}