#include<iostream>
#include<cstdio>
#include<queue>
#include<set>
#include<vector>
#include<map>
#include<algorithm>
#include<cassert>
using namespace std;
#define pb push_back
#define mp make_pair
#define fr first
#define sc second
typedef pair<int, int> Point;
typedef pair<Point, Point> Segment;
static const int INF = (1<<30);
static const int NMAX = (1<<18); // 131072 * 2

// seg trees
set<int> SH[NMAX*2-1];
set<int> SV[NMAX*2-1];
// line
set<pair<int, int> > LH[NMAX];
set<pair<int, int> > LV[NMAX];

void init(){
  for ( int i = 0; i < 2*NMAX-1; i++ ){
    SH[i].insert(-1);
    SH[i].insert(INF);
    SV[i].insert(-1);
    SV[i].insert(INF);
  }
  for ( int i = 0; i < NMAX; i++ ){
    LH[i].insert(mp(-2, -1));
    LH[i].insert(mp(INF, INF+1));
    LV[i].insert(mp(-2, -1));
    LV[i].insert(mp(INF, INF+1));
  }
}

bool checkCross(int i, int s, int e, set<int> S[] ){
  i += NMAX - 1; // to seg node id

  if ( S[i].lower_bound(s) != S[i].upper_bound(e) ) return false;
  while( i > 0 ){
    i = (i-1)/2;
    if ( S[i].lower_bound(s) != S[i].upper_bound(e) ) return false;
  }
  return true;
}

bool checkLine(int i, int a, int b, set<pair<int, int> > L[]){
  set<pair<int, int> >::iterator it = L[i].lower_bound(mp(a, a));
  pair<int, int> t = *it;
  it--;
  pair<int, int> s = *it;
  return s.sc < a && b < t.fr;
}

void placeCross(int v, int a, int b, int k, int l, int r, set<int> S[]){
  if ( r <= a || b <= l) return;
  if ( a <= l && r <= b ) {
    S[k].insert(v);
  } else {
    placeCross(v, a, b, k*2 + 1, l, (l+r)/2, S);
    placeCross(v, a, b, k*2 + 2, (l+r)/2, r, S);
  }
}

void placeLine(int v, int a, int b, set<pair<int, int> > L[]){
  L[v].insert(mp(a, b));
}

void solve(vector<Segment> &S){
  init();
  int a, b, v;
  for ( int i = 0; i < S.size(); i++ ){
    Segment s = S[i];
    if ( s.first.second == s.second.second ) { // H
      a = s.first.first;  // x
      b = s.second.first; // y
      v = s.first.second; assert( s.first.second == s.second.second);
      if ( checkLine(v, a, b, LH) && checkCross(v, a, b, SH) ){
	placeCross(v, a, b+1, 0, 0, NMAX, SV);
	placeLine(v, a, b, LH);
	printf("1\n");
      } else 	printf("0\n");
    } else {
      a = s.first.second;
      b = s.second.second;
      v = s.first.first; assert( s.first.first == s.second.first);
      if ( checkLine(v, a, b, LV) && checkCross(v, a, b, SV) ){
	placeCross(v, a, b+1, 0, 0, NMAX, SH);
	placeLine(v, a, b ,LV);
	printf("1\n");
      } else 	printf("0\n");
    }
  }
}

void compress(vector<Segment> &S){
  set<int> X, Y;
  map<int, int> MX, MY;
  int nx, ny;

  for ( int i = 0; i < S.size(); i++ ){
    X.insert(S[i].fr.fr);
    X.insert(S[i].sc.fr);
    Y.insert(S[i].fr.sc);
    Y.insert(S[i].sc.sc);
  }

  nx = ny = 0;
  for ( set<int>::iterator it = X.begin(); it != X.end(); it++ ){
    MX[*it] = nx++;
  }
  for ( set<int>::iterator it = Y.begin(); it != Y.end(); it++ ){
    MY[*it] = ny++;
  }

  for ( int i = 0; i < S.size(); i++ ){
    int sx = MX[S[i].fr.fr];
    int sy = MY[S[i].fr.sc];
    int tx = MX[S[i].sc.fr];
    int ty = MY[S[i].sc.sc];
    pair<int, int> p1 = mp(sx, sy);
    pair<int, int> p2 = mp(tx, ty);

    if ( sy == ty ){
      if ( p1.fr > p2.fr ) swap(p1, p2);
    } else {
      assert( sx == tx );
      if ( p1.sc > p2.sc ) swap(p1, p2);
    }

    S[i] = mp(p1, p2);
  }
}

int main(){
  int N;
  int sx, sy, tx, ty;
  vector<Segment> S;
  scanf("%d", &N);
  for ( int i = 0; i < N; i++ ){
    scanf("%d %d %d %d", &sx, &sy, &tx, &ty);
    S.pb(mp(mp(sx, sy), mp(tx, ty)));
  }
  compress(S);
  solve(S);

  return 0;
}

Measured memory_bytes: 244588