#include <iostream>
#include <cstdio>
#include <vector>
#define _USE_MATH_DEFINES
#include <math.h>
#include <cstring>
#include <numeric>
#include <algorithm>
#include <stdlib.h>
#include <functional>
#include <string>
#include <array>
#include <map>
#include <queue>
#include <limits.h>
#include <set>
#include <stack>
#include <random>
#include <complex>
#include <unordered_map>
#include <nmmintrin.h>
#include <chrono>
const double EPS = 1e-8;
#define Scan(a) int a;scanf("%d", &a);
#define ScanS(a) char a[500];scanf("%s", a);
#define rep(i,s,n) for(int i = (s); (n) > i; i++)
#define REP(i,n) rep(i,0,n)
#define RANGE(x,a,b) ((a) <= (x) && (x) <= (b))
#define DUPLE(a,b,c,d) (RANGE(a,c,d) || RANGE(b,c,d) || RANGE(c,a,b) || RANGE(d,a,b))
#define INCLU(a,b,c,d) (RANGE(a,c,d) && (b,c,d))
#define PW(x) ((x)*(x))
#define ALL(x) (x).begin(), (x).end()
#define MODU 1000000007
#define bitcheck(a,b)   ((a >> b) & 1)
#define bitset(a,b)      ( a |= (1 << b))
#define bitunset(a,b)    (a &= ~(1 << b))
#define MP(a,b) make_pair((a),(b))
#define Manh(a,b) (abs((a).first-(b).first) + abs((a).second - ((b).second))
#define pritnf printf
#define scnaf scanf
#define itn int
#ifdef _MSC_VER
#define __builtin_popcount _mm_popcnt_u32
#define __builtin_popcountll _mm_popcnt_u64
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
ll gcd(ll a, ll b) {
	if (b == 0) return a;
	return gcd(b, a%b);
}
template<typename A, size_t N, typename T>
void Fill(A(&array)[N], const T &val) {
	std::fill((T*)array, (T*)(array + N), val);
}
class Lazy_Segment_Tree {//0-indexed ??????
public:
	vector<set<int>> data;
	int n;
	Lazy_Segment_Tree(int a) :n(1) {
		while (n < a) n *= 2;
		data.resize(n * 2 - 1);
	}
	void op(int a, int b, int v, int num = 0, int base = 1) {
		int l = (num + 1 - base) * (n / base), r = l + n / base;
		if (a == l && b == r) {
			data[num].insert(v);
		}
		else {
			int nr = (l + r) / 2;
			if (nr > a) op(a, min(b, nr), v, num * 2 + 1, base * 2);
			if (nr < b) op(max(a, nr), b, v, num * 2 + 2, base * 2);
		}
	}

	bool query(int a, pii que, int num = 0, int base = 1) {
		int l = (num + 1 - base) * (n / base), r = l + n / base;

		if (r-l == 1) {
			return data[num].lower_bound(que.first) != data[num].upper_bound(que.second);
		}
		else {
			int nr = (l + r) / 2;
			bool ret = data[num].lower_bound(que.first) != data[num].upper_bound(que.second);
			if (nr > a) ret |= query(a, que, num * 2 + 1, base * 2);
			else ret |= query(a, que, num * 2 + 2, base * 2);
			return ret;
		}
	}
};



int main() {
	int n;
	cin >> n;
	
	map<int, int> x, y;
	vector<int> xz,yz;
	vector<pair<pii, pii>> ln;
	REP(i, n) {
		int a, b, c, d;
		scanf("%d %d %d %d", &a ,&b, &c, &d);

		ln.push_back({ { min(a,c), min(b, d) }, {max(a,c), max(b,d)} });

		xz.push_back(a);
		xz.push_back(c);
		yz.push_back(b);
		yz.push_back(d);
	}

	sort(ALL(xz));
	sort(ALL(yz));
	xz.erase(unique(ALL(xz)), xz.end());
	yz.erase(unique(ALL(yz)), yz.end());


	REP(i, xz.size())
		x[xz[i]] = i;
	REP(i, yz.size())
		y[yz[i]] = i;

	Lazy_Segment_Tree xs(xz.size()), ys(yz.size());

	for (auto& itr : ln) {
		itr.first.first = x[itr.first.first];
		itr.first.second = y[itr.first.second];
		itr.second.first = x[itr.second.first];
		itr.second.second = y[itr.second.second];
	}

	vector<set<pair<int,bool>>> px(yz.size()), py(xz.size());

	for (auto cl : ln) {

		if (cl.first.first == cl.second.first) {
			int an = xs.query(cl.first.first,{ cl.first.second, cl.second.second });

			auto itr = py[cl.first.first].upper_bound({ cl.second.second, 1 });
			an |= py[cl.first.first].lower_bound({ cl.first.second, 0 }) != itr;
			if(itr != py[cl.first.first].end())
				an |= py[cl.first.first].upper_bound({ cl.second.second, 1 })->second;

			printf("%d\n", !an);
			if (!an) {
				ys.op(cl.first.second, cl.second.second + 1, cl.first.first);
				py[cl.first.first].insert({ cl.first.second, 0 });
				py[cl.first.first].insert({ cl.second.second, 1 });
			}
		}
		else {
			int an = ys.query(cl.first.second, { cl.first.first, cl.second.first });
			auto itr = px[cl.first.second].upper_bound({ cl.second.first, 1 });
			an |= px[cl.first.second].lower_bound({ cl.first.first, 0 }) != itr;
			if(itr != px[cl.first.second].end())
				an |= itr->second;
			printf("%d\n", !an);

			if (!an) {
				xs.op(cl.first.first, cl.second.first + 1, cl.first.second);
				px[cl.first.second].insert({ cl.first.first,0 });
				px[cl.first.second].insert({ cl.second.first, 1 });
			}
		}
	}

	return 0;
}