#include<bits/stdc++.h>
#define L (x<<1)
#define R (x<<1|1)
using namespace std;
const int N=1e5+5,MAX=1e9;
struct Stree{
int l,r;
int cnt,id,tag;
int Max;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define cnt(x) tree[x].cnt
#define id(x) tree[x].id
#define Max(x) tree[x].Max
#define tag(x) tree[x].tag
}tree[N<<4];
struct line{
int l,r,x,w;
bool operator <(const line &ln)const{
if(x!=ln.x)return x<ln.x;
return w>ln.w;
}
}a[N<<2];
int n,cnt,len;
int A[N<<2];
long long Max;
int ansl,ansr=MAX+10;
void up(int x){
if(Max(L)>=Max(R)){
Max(x)=Max(L);
id(x)=id(L);
}else{
Max(x)=Max(R);
id(x)=id(R);
}
}
void spread(int x){
Max(L)+=tag(x);
Max(R)+=tag(x);
tag(L)+=tag(x);
tag(R)+=tag(x);
tag(x)=0;
}
void build(int x=1,int l=1,int r=len-1){
l(x)=l;
r(x)=r;
if(l==r){
id(x)=l;
return;
}
int mid=l+r>>1;
build(L,l,mid);
build(R,mid+1,r);
up(x);
}
void update(int x,int l,int r,int k){
if(l<=A[l(x)]&&A[r(x)+1]<=r){
Max(x)+=k;
tag(x)+=k;
return;
}
spread(x);
if(l<A[r(L)+1])update(L,l,r,k);
if(r>A[l(R)])update(R,l,r,k);
up(x);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int l,r;
cin>>l>>r;
if(0<=l-1&&l+1<=r-1){
a[++cnt]=(line){l+1,r-1,0,1};
a[++cnt]=(line){l+1,r-1,l-1,-1};
A[++len]=l+1;
A[++len]=r-1;
}
if(l+1<=r-1&&r+1<=MAX){
a[++cnt]=(line){r+1,MAX,l+1,1};
a[++cnt]=(line){r+1,MAX,r-1,-1};
A[++len]=r+1;
A[++len]=MAX;
}
}
if(!len){
cout<<"0 1";
return 0;
}
sort(a+1,a+1+cnt);
sort(A+1,A+1+len);
len=unique(A+1,A+1+len)-A;
build();
ansr=1;
for(int i=1;i<=cnt;i++){
update(1,a[i].l,a[i].r,a[i].w);
if(Max(1)>Max){
Max=Max(1);
ansl=a[i].x;
ansr=A[id(1)];
}else if(Max(1)==Max&&a[i].x==ansl)
ansr=max(1,min(ansr,A[id(1)]));
}
cout<<ansl<<' '<<ansr;
return 0;
}