#include <bits/stdc++.h>
#pragma optimization_level 3
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math,O3")
using namespace std;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
long long win(long long x, long long y) {
  if (y % 2 == 1) return x % 2 == 0 ? 1 : 0;
  if (y % 4 == 2) {
    if (x == y) return 0;
    if (x == y - 1) return 1;
    return win(x, y - 2);
  }
  assert(y % 4 == 0);
  long long fir = y / 4, sec = y / 2;
  if (x <= fir) return win(x, y / 4);
  if (x <= sec) return 1;
  return x % 2 == 0 ? 0 : 1;
}
long long lose(long long x, long long y) {
  if (y % 2 == 1) return x == y ? 1 : lose(x, y - 1);
  long long fir = y / 2;
  if (x <= fir) return win(x, y / 2);
  return 1;
}
int main() {
  cin.tie(0);
  cout.tie(0);
  cin.sync_with_stdio(0);
  cout.sync_with_stdio(0);
  ;
  long long a;
  cin >> a;
  vector<pair<long long, long long> > n(a);
  for (int q = 0; q < a; q++) cin >> n[q].first >> n[q].second;
  long long dp[a][2][2], can[a][2];
  memset(dp, 0, sizeof(dp));
  memset(can, -1, sizeof(can));
  dp[0][0][0] = lose(n[0].first, n[0].second);
  dp[0][0][1] = win(n[0].first, n[0].second);
  can[0][0] = dp[0][0][0];
  can[0][1] = dp[0][0][1];
  for (int q = 1; q < a; q++) {
    int ls = lose(n[q].first, n[q].second);
    int wn = win(n[q].first, n[q].second);
    if (can[q - 1][0]) {
      dp[q][0][0] = ls;
      dp[q][0][1] = wn;
    }
    if (can[q - 1][1]) {
      dp[q][1][0] = ls ^ 1;
      dp[q][1][1] = wn ^ 1;
    }
    can[q][0] = dp[q][0][0] | dp[q][1][0];
    can[q][1] = dp[q][0][1] | dp[q][1][1];
  }
  cout << can[a - 1][1] << " " << can[a - 1][0];
}
